实施信息: 我已经实施了一个 3 窗格布局,遵循 CommonsWare 对他自己的问题的回复:Gmail 三片段动画场景的完整工作示例?
作为一个总体思路,我的布局由以下级别(1 到 3)组成:
MainActivity
SlidingMenu
(Side Drawer UI 模式)片段隐藏在左侧,ContentFragment
作为容纳 3 窗格布局的片段。- 在
ContentFragment
:LeftListFragment
(每行有 3 个 TextViews 的行),MiddleListFragment
(每行有 8 个 TextViews 的行),DetailFragment
.
LeftListFragment
并MiddleListFragment
用于CursorLoaders
从ContentProvider
每个列表中加载数据。DetailFragment
还需要在需要时使用带有数据的游标。所以我什至没有实现自定义Adapters
(这种方式更好的设计)。然后我添加了 3 窗格布局 + 动画。就工作而言,它按预期工作,没有问题。Animation
时间为 500 毫秒。
问题: 动画有点卡顿。一些丢帧。当左侧和中间都可见并且我单击中间列表项以打开详细信息时;以及当我点击后退按钮再次查看左侧和中间列表时(实际上没有加载任何内容)。
我试过的:
- 删除了加载片段的代码
DetailView
。我只需点击一个项目,MiddleFragment
动画就开始了,实际上没有加载任何细节。还是口吃。此外,当回击时,没有任何负载并且它仍然口吃,所以我认为加载器/光标不是造成这种情况的原因。 - 我使用 dumpsys gfxinfo 来查看计算每一帧的平均时间(以毫秒为单位)。实际上,计算的平均时间是 18 毫秒,高于 16 毫秒的阈值。那么这是否意味着口吃是因为在制作动画时再次绘制列表需要时间?如果是这样,为什么?我的意思是......我在行视图中根本没有任何图像。而且我不能搞砸适配器代码,因为我还没有写任何...
Animation
将时间从 500 毫秒减少到 200 毫秒。如果你仔细观察它仍然会卡顿,它只是更快。
编辑:我从下面切换rightPaneWidth
到leftPaneWidth
下面(是的,这删除了重新调整尺寸的动画),现在口吃消失了。该列表仍向左侧滑动,但宽度并没有变小。因此,如果现在不再出现口吃,这是否意味着我的代码中的 ObjectAnimator 存在问题?
ObjectAnimator.ofInt(this, "middleWidth", rightPaneWidth, leftPaneWidth)
.setDuration(ANIM_DURATION).start();
谢谢你的时间 !
3 窗格布局的代码:
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>