给item添加动画有3种方法:
- 在onBindViewHolder()
里面中给item设置动画
- 自定义ItemAnimator
,比如DefaultItemAnimator
- 自定义布局动画(LayoutAnimation)
参考:RecyclerView 与 LayoutAnimation 实现的进入动画(一 ): List
我们采用第三种,有2种使用方式,一种是java代码,另一种是xml中引用动画资源文件。
LayoutAnimationController loadLayoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_slide_in_right);
recyclerView.setLayoutAnimation(loadLayoutAnimation);
XML中引用:
.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layoutAnimation="@anim/layout_animation_slide_in_bottom"
android:layout_height="match_parent"/>
详细:
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
LayoutAnimationController loadLayoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_slide_in_bottom);
recyclerView.setLayoutAnimation(loadLayoutAnimation);
recyclerView.setAdapter(new MyAdapter());
R.anim.layout_animation_slide_in_bottom
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_slide_in_bottom"
android:animationOrder="normal"
android:delay="15%"
android:interpolator="@android:anim/overshoot_interpolator"/>
animation:动画资源
animationOrder:动画顺序
delay:上一个item动画执行15%的时候,下一个item的动画才执行
item_slide_in_bottom:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fillAfter="true"
android:shareInterpolator="true">
<translate
android:fromXDelta="0"
android:fromYDelta="50%p"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="0"
android:toYDelta="0"/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"/>
set>
recyclerView.setLayoutAnimation(loadLayoutAnimation);
recyclerView.getAdapter().notifyDataSetChanged();
//adapter.notifyDataSetChanged();//也可以
recyclerView.scheduleLayoutAnimation();
实际操作发现去掉recyclerView.scheduleLayoutAnimation();
也可以:
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_slide_in_right);
recyclerView.setLayoutAnimation(animation);
adapter.notifyDataSetChanged();
加入item有30个,一屏幕只显示10个,我们切换动画时,导致item闪屏。但是如果我们把30条item都滑动一遍后,在切换另外一种LayoutAnimation,那么不会有闪屏。
找到一种解决方案,没有试过。解决RecyclerView notifyItem闪屏问题
recyclerView.getItemAnimator().setChangeDuration(0);
或
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
参考:RecyclerView 与 LayoutAnimation 实现的进入动画(二 ): Grid
其实吧LayoutAnimation
放到RecyclerView
也是可以的,只不过item是一行一行加载,第一行加载结束,第二行才开始加载,以此类推(每一行最后一个加载delay,第二行才开始加载),我们想要每一行同时加载的效果,就需要重新RecyclerView
。
RecyclerView
这是因为RecyclerView是使用LayoutManager来布局自己的子view的,它并不知道LayoutManager如何放置子view。因此RecyclerView不知道到底该把AnimationParameter应用到list上还是grid上,而默认是list。为了修复这个问题我们需要一个自定义的RecyclerView,让它知道GridLayoutManager的存在
public class GridRecyclerView extends RecyclerView {
public GridRecyclerView(Context context) {
super(context);
}
public GridRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public GridRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params,
int index, int count) {
final LayoutManager layoutManager = getLayoutManager();
if (getAdapter() != null && layoutManager instanceof GridLayoutManager) {
GridLayoutAnimationController.AnimationParameters animationParams =
(GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
if (animationParams == null) {
// If there are no animation parameters, create new once and attach them to
// the LayoutParams.
animationParams = new GridLayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
}
// Next we are updating the parameters
// Set the number of items in the RecyclerView and the index of this item
animationParams.count = count;
animationParams.index = index;
// Calculate the number of columns and rows in the grid
final int columns = ((GridLayoutManager) layoutManager).getSpanCount();
animationParams.columnsCount = columns;
animationParams.rowsCount = count / columns;
// Calculate the column/row position in the grid
final int invertedIndex = count - 1 - index;
animationParams.column = columns - 1 - (invertedIndex % columns);
animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns;
} else {
// Proceed as normal if using another type of LayoutManager
super.attachLayoutAnimationParameters(child, params, index, count);
}
}
}
同LayoutAnimation一样,既可以在xml中配置,也可以在java中设置。
<com.cqc.recyclyviewitemanimation01.view.GridRecyclerView
......
android:layoutAnimation="@anim/grid_layout_animation"/>
java
LayoutAnimationController loadLayoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.grid_layout_animation);
recyclerView.setLayoutAnimation(loadLayoutAnimation);
grid_layout_animation.xml
:属性都好理解。
<gridLayoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_slide_in_right"
android:columnDelay="15%"
android:direction="left_to_right|top_to_bottom"
android:directionPriority="row"
android:rowDelay="15%"/>