給item添加動畫有3種方法:
- 在onBindViewHolder()
裏面中給item設置動畫
- 自定義ItemAnimator
,比如DefaultItemAnimator
- 自定義佈局動畫(LayoutAnimation)
LayoutAnimation
參考:RecyclerView 與 LayoutAnimation 實現的進入動畫(一 ): List
效果圖
使用方式
我們採用第三種,有2種使用方式,一種是java代碼,另一種是xml中引用動畫資源文件。
LayoutAnimationController loadLayoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_slide_in_right);
recyclerView.setLayoutAnimation(loadLayoutAnimation);
XML中引用:
<android.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
<?xml version="1.0" encoding="utf-8"?>
<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:
<?xml version="1.0" encoding="utf-8"?>
<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的閃屏問題
加入item有30個,一屏幕只顯示10個,我們切換動畫時,導致item閃屏。但是如果我們把30條item都滑動一遍後,在切換另外一種LayoutAnimation,那麼不會有閃屏。
找到一種解決方案,沒有試過。解決RecyclerView notifyItem閃屏問題
recyclerView.getItemAnimator().setChangeDuration(0);
或
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
GridLayoutAnimation
參考: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);
}
}
}
GridLayoutAnimation
同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
:屬性都好理解。
<?xml version="1.0" encoding="utf-8"?>
<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%"/>