当前位置: 首页 > 知识库问答 >
问题:

3窗格布局片段动画结巴

颜嘉誉
2023-03-14

实现信息:我已经实现了一个3窗格布局,以下是CommonsWare对他自己的问题的回应:Gmail三片段动画场景的完整工作示例?

总体而言,我的布局由以下级别(1到3)组成:

  1. MainActivity
  2. SlidingMenu(侧抽屉UI模式)隐藏在左侧的片段,而ContentFragment作为存放3窗格布局的片段。
  3. ContentFragment内部:LeftListFragment(每行具有3个文本视图)、MiddlelistFragment(每行具有8个文本视图)、DetailFragment

LeftListFragmentMiddlelistFragment使用CursorLoaders从每个列表中的ContentProvider加载数据。detailfragment还在需要时调用带有数据的游标。所以我甚至没有实现自定义适配器(这样设计更好)。然后我添加了3个窗格布局+动画。就工作而言,它按预期工作,没有问题。动画时间为500ms。

问题是:动画有点结巴。几个掉帧。当左边和中间都是可见的,并且我点击中间的列表项打开一个细节;当我点击后退按钮再次看到左边和中间列表时(实际上没有加载任何东西)。

我试过的:

  1. 删除了在detailview中加载片段的代码。我只需点击middlefragment中的一个项目,动画就开始了,实际上没有加载任何细节。还是口吃。而且,当回击时,没有任何东西加载并且仍然结巴,所以我认为加载器/游标不是导致这种情况的原因。
  2. 我使用dumpsys gfxinfo查看计算每个帧的平均时间(毫秒)。实际上,一次计算的平均时间为18ms,高于16ms阈值。那么这是否意味着口吃是因为在动画时再次绘制列表所花费的时间?如果是,为什么?我是说...我在行视图中没有任何图像。而且我不能搞砸适配器代码,因为我还没有编写任何...
  3. 动画时间从500ms减少到200ms。如果你真的仔细看,它还是会结巴的,它只是更快了。
ObjectAnimator.ofInt(this, "middleWidth", rightPaneWidth, leftPaneWidth)
                    .setDuration(ANIM_DURATION).start();
package com.xyz.view.widget;

import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.LinearLayout;


public class ThreePaneLayout extends LinearLayout
{
    private View leftView = null;
    private View middleView = null;
    private View rightView = null;

private static final int ANIM_DURATION = 500;
private int leftPaneWidth = -1;
private int rightPaneWidth = -1;


// -------------------------------------------------------------------------------------------
// --------------   Constructor
// -------------------------------------------------------------------------------------------


public ThreePaneLayout(Context context, AttributeSet attrs)
{
    super(context, attrs);
    setOrientation(HORIZONTAL);
}

@Override
public void onFinishInflate()
{
    super.onFinishInflate();
    leftView = getChildAt(0);
    middleView = getChildAt(1);
    rightView = getChildAt(2);
}


// -------------------------------------------------------------------------------------------
// --------------   Public methods
// -------------------------------------------------------------------------------------------


public View getLeftView()
{
    return leftView;
}

public View getMiddleView()
{
    return middleView;
}

public View getRightView()
{
    return rightView;
}

@SuppressLint("NewApi")
public void hideLeft()
{
    if (leftPaneWidth == -1)
    {

        leftPaneWidth = leftView.getWidth();
        rightPaneWidth = middleView.getWidth();
        resetWidget(leftView, leftPaneWidth);
        resetWidget(middleView, rightPaneWidth);
        resetWidget(rightView, rightPaneWidth);
        requestLayout();
    }
    translateWidgets(-1 * leftPaneWidth, leftView, middleView, rightView);
    ObjectAnimator.ofInt(this, "middleWidth", rightPaneWidth, leftPaneWidth)
                    .setDuration(ANIM_DURATION).start();
}

@SuppressLint("NewApi")
public void showLeft()
{
    translateWidgets(leftPaneWidth, leftView, middleView, rightView);
    ObjectAnimator.ofInt(this, "middleWidth", leftPaneWidth, rightPaneWidth)
                    .setDuration(ANIM_DURATION)
                    .start();
}


// -------------------------------------------------------------------------------------------
// --------------   Private methods
// -------------------------------------------------------------------------------------------


private void setMiddleWidth(int value)
{
    middleView.getLayoutParams().width = value;
    requestLayout();
}

@TargetApi(12)
private void translateWidgets(int deltaX, View... views)
{
    for (final View view : views)
    {
        ViewPropertyAnimator viewPropertyAnimator = view.animate();
        viewPropertyAnimator.translationXBy(deltaX)
                            .setDuration(ANIM_DURATION);
    }
  }

  private void resetWidget(View view, int width)
  {
      LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)view.getLayoutParams();  
      layoutParams.width = width;
      layoutParams.weight = 0;
  }
}

ContentFragment的XML:

    <?xml version="1.0" encoding="utf-8"?>
<com.xyz.view.widget.ThreePaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_content_three_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<FrameLayout
    android:id="@+id/fragment_content_framelayout_left"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="3" />

<FrameLayout
    android:id="@+id/fragment_content_framelayout_middle"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="7" />

<FrameLayout
    android:id="@+id/fragment_content_framelayout_right"
    android:layout_width="0dp"
    android:layout_height="match_parent" />
</com.xyz.view.widget.ThreePaneLayout>

共有1个答案

钱睿范
2023-03-14

问题不是ObjectAnimator,而是您的应用程序在动画的每一帧上做得太多了。具体地说,您正在对布局参数进行动画化,并在每个帧上请求布局。布局强大有用...但在除最琐碎的视图层次结构之外的任何其他视图层次结构中都可能非常昂贵。在动画过程中避免每帧进行昂贵的操作是很重要的,而布局就属于这种“昂贵”的范畴。滑动东西是好的(翻译x/y),淡入/淡出东西是好的(alpha),但实际上把东西放在每一帧上?说不就行了。

 类似资料:
  • 我是一个Java/JavaFX程序员新手,我正在开发一个简单的JavaFX建筑设计工具,在这个工具中,您可以画出墙壁、地板等,因此对象(主要是线、圆、多边形、矩形图像)是在屏幕上绘制和创建的,而不是在运行之前创建的。

  • 在构建场景中的所有必需节点之后,我们通常会按顺序排列它们。 容器内部件的这种布置称为容器的布局。 我们还可以说我们遵循布局,因为它包括将所有组件放置在容器内的特定位置。 JavaFX提供了几种预定义的布局,如HBox, VBox, Border Pane, Stack Pane, Text Flow, Anchor Pane, Title Pane, Grid Pane, Flow Panel等。

  • 我已经使用Android ADT几个星期了,我曾经通过转到:文件来创建新活动 当我选择“新建空白活动”并单击“下一步”时,会显示一个我必须填写的新表格,标题为“片段布局名称”。为什么这突然出现,有谁知道为什么我被迫创建一个片段布局,因为我甚至不想使用它。我还记得我的一个朋友说他大约一周前更新了他的SDK,他说他有同样的问题。我是否应该在XML文档加载后删除其中的片段,或者有没有一种方法可以禁用它,

  • 我希望通过向窗格中添加gridPanes来使用JavaFX来建模一个简单的微波。微波 上面是结果应该是什么样子的,但是我在正确布置网格窗格时遇到了麻烦。

  • 我有一个小问题。我试图用JavaFX2.0创建一个好的GUI(可以调整大小),但我有一个小问题。我使用的是网格窗格,但当我在其中放置多个按钮时,当我将屏幕大小调整为较小尺寸时,按钮将以屏幕左侧的大小相互滑动。我可以为单元格或其他东西设置最小大小吗?我正在使用FXML进行设计。非常感谢你!

  • 我有一个RelativeLayout,其中两个LinearLayout和一个TextView(三个都是孩子)共享同一个空间,这意味着在任何给定点上,只有一个视图可见,而其他两个视图消失。在应用程序启动时,TextView是可见视图。我有一个按钮,可以启动动画,使文本视图淡出,线性布局淡入。另一个线性布局还有一个按钮。 逻辑如下: 按下按钮- 只要上面的交互使用相同的按钮(对于相同的线性布局),这就