我试图用新的RecyclerView(使用GridLayoutManager)替换我的GridView,但似乎它不能很好地处理gridLayoutAnimation(ClassCastException: LayoutAnimationController$AnimationParameters cannot be cast to GridLayoutAnimationController$AnimationParameters
)。它适用于常规布局动画,但因为它是一个网格,所以在平板电脑上完成它需要很长时间。
我想要完成的工作与Hierarchical Timing类似。如果您查看示例视频,它会显示布局动画从左上角到右下角。常规布局动画将逐行执行动画,因此在更大的网格(例如平板电脑)上花费太多时间来完成。我也曾尝试过探索ItemAnimator,但这只能在所有单元格上同时运行动画,就像在" Don&#t;"示例
有没有办法在RecyclerView中完成此网格布局动画?
这是gridview_layout_animation.xml:
<!-- replace gridLayoutAnimation with layoutAnimation and -->
<!-- replace column- and rowDelay with delay for RecyclerView -->
<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:columnDelay="15%"
android:rowDelay="15%"
android:animation="@anim/grow_in"
android:animationOrder="normal"
android:direction="top_to_bottom|left_to_right"
android:interpolator="@android:interpolator/linear"
/>
这是动画grow_in.xml:
<set android:shareInterpolator="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="@android:interpolator/decelerate_quint"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="400"
android:startOffset="200"
/>
</set>
编辑:根据Galaxas0的回答,here是一种解决方案,只需要您使用扩展RecyclerView
的自定义视图。基本上只覆盖attachLayoutAnimationParameters()
方法。使用此<gridLayoutAnimation>
可以像使用GridView一样工作。
public class GridRecyclerView extends RecyclerView {
public GridRecyclerView(Context context) {
super(context);
}
public GridRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setLayoutManager(LayoutManager layout) {
if (layout instanceof GridLayoutManager){
super.setLayoutManager(layout);
} else {
throw new ClassCastException("You should only use a GridLayoutManager with GridRecyclerView.");
}
}
@Override
protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) {
if (getAdapter() != null && getLayoutManager() instanceof GridLayoutManager){
GridLayoutAnimationController.AnimationParameters animationParams =
(GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
if (animationParams == null) {
animationParams = new GridLayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
}
int columns = ((GridLayoutManager) getLayoutManager()).getSpanCount();
animationParams.count = count;
animationParams.index = index;
animationParams.columnsCount = columns;
animationParams.rowsCount = count / columns;
final int invertedIndex = count - 1 - index;
animationParams.column = columns - 1 - (invertedIndex % columns);
animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns;
} else {
super.attachLayoutAnimationParameters(child, params, index, count);
}
}
}
答案 0 :(得分:5)
LayoutAnimationController
与ViewGroup
相关联,ListView
和GridView
都扩展了以下方法,以提供孩子animationParams
。问题是GridLayoutAnimationController
需要自己的AnimationParameters
无法进行分类。
/**
* Subclasses should override this method to set layout animation
* parameters on the supplied child.
*
* @param child the child to associate with animation parameters
* @param params the child's layout parameters which hold the animation
* parameters
* @param index the index of the child in the view group
* @param count the number of children in the view group
*/
protected void attachLayoutAnimationParameters(View child,
LayoutParams params, int index, int count) {
LayoutAnimationController.AnimationParameters animationParams =
params.layoutAnimationParameters;
if (animationParams == null) {
animationParams = new LayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
}
animationParams.count = count;
animationParams.index = index;
}
由于默认情况下此方法会添加LayoutAnimationController.AnimationParameters
而不是GridLayoutAnimationController.AnimationParameters
,因此修复应该是事先创建并附加一个。我们需要实现的是GridView
已经做了什么:
@Override
protected void attachLayoutAnimationParameters(View child,
ViewGroup.LayoutParams params, int index, int count) {
GridLayoutAnimationController.AnimationParameters animationParams =
(GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
if (animationParams == null) {
animationParams = new GridLayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
}
animationParams.count = count;
animationParams.index = index;
animationParams.columnsCount = mNumColumns;
animationParams.rowsCount = count / mNumColumns;
if (!mStackFromBottom) {
animationParams.column = index % mNumColumns;
animationParams.row = index / mNumColumns;
} else {
final int invertedIndex = count - 1 - index;
animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns);
animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns;
}
}
要复制GridView
,我们可以做的最接近的事情是将修改变为onBindViewHolder()
,允许它们在触发动画的dispatchDraw
之前运行。
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
GridLayoutAnimationController.AnimationParameters animationParams = new GridLayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
animationParams.count = 9;
animationParams.columnsCount = 3;
animationParams.rowsCount = 3;
animationParams.index = position;
animationParams.column = position / animationParams.columnsCount;
animationParams.row = position % animationParams.columnsCount;
如果使用RecyclerView
的新GridLayoutManager
,请尝试从中获取参数。上面的示例是一个概念证明,表明它的工作原理。我的硬编码值也不适用于我的应用程序。
由于这是自API 1以来没有真正文档或样本的API,我强烈建议不要使用它,因为有很多方法可以复制其功能。
答案 1 :(得分:3)
更简单的解决方案
TransitionManager.beginDelayedTransition(moviesGridRecycler);
gridLayoutManager.setSpanCount(gridColumns);
adapter.notifyDataSetChanged();
但不要忘记制作您的RecyclerAdapter setHasStableIds(true);
并实施getItemID()
@Override
public long getItemId(int position) {
return yourItemSpecificLongID;
}
答案 2 :(得分:0)
在https://gist.github.com/Musenkishi/8df1ab549857756098ba
引用@Musenkishi毫无头绪。设置适配器后是否正在调用
recyclerView.scheduleLayoutAnimation();
?您是否已将android:layoutAnimation="@anim/your_layout_animation"
设置为布局中的<GridRecyclerView>
?
这解决了我的问题。