Android RecyclerView布局动画
在本教程中,我们将在Android应用程序中讨论和实现RecyclerView布局动画。
Android RecyclerView布局动画
有很多方法可以使RecyclerView中的行动起来。
两种常用的经过测试的方法是:
使用ItemAnimators。
–阅读本教程。在Adapter类的
onBindViewHolder中的每一行上设置动画
还有另一种鲜为人知但更有效的使用布局动画为RecyclerView设置动画的方法。
我们可以直接在XML中将动画资源资产传递给属性" android:layoutAnimation"。
传递的动画资源必须包含<layoutAnimation>作为根标记。
layoutAnimation在除RecyclerView之外的所有其他布局上均有效。
首先,在Android Studio项目中的res |anim文件夹中定义一些基本的动画。
down_to_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="50%p"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toYDelta="0"
<alpha
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1"
</set>
up_to_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="-25%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toYDelta="0"
<alpha
android:fromAlpha="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:toAlpha="1"
<scale
android:fromXScale="125%"
android:fromYScale="125%"
android:interpolator="@android:anim/decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="100%"
android:toYScale="100%"
</set>
left_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromXDelta="-100%p"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0"
<alpha
android:fromAlpha="0.5"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1"
</set>
right_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromXDelta="100%p"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0"
<alpha
android:fromAlpha="0.5"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1"
</set>
现在,我们为每个动画集创建layoutAnimation。
layout_animation_down_to_up.xml
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="https://schemas.android.com/apk/res/android" android:animation="@anim/down_to_up" android:animationOrder="normal" android:delay="15%"
layout_animation_up_to_down.xml
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="https://schemas.android.com/apk/res/android" android:animation="@anim/up_to_down" android:animationOrder="normal" android:delay="15%"
layout_animation_left_to_right.xml
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="https://schemas.android.com/apk/res/android" android:animation="@anim/left_to_right" android:animationOrder="normal" android:delay="15%"
layout_animation_right_to_left.xml
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="https://schemas.android.com/apk/res/android" android:animation="@anim/right_to_left" android:animationOrder="normal" android:delay="15%"
以XML和编程方式设置布局动画
我们可以通过以下方式在RecyclerView上以XML设置布局动画:
<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:layoutAnimation="@anim/layout_animation_right_to_left"
以编程方式:
int resId = R.anim.layout_animation_right_to_left; LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(context, resId); recyclerView.setLayoutAnimation(animation);
为了重新运行动画,或者如果RecyclerView的数据集已更改,则使用以下代码:
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_right_to_left);
recyclerView.setLayoutAnimation(controller);
recyclerView.getAdapter().notifyDataSetChanged();
recyclerView.scheduleLayoutAnimation();
代码
下面给出了activity_main.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation_up_to_down"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@android:drawable/ic_media_next"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
</android.support.constraint.ConstraintLayout>
FloatingActionButton用于切换不同的布局动画。
RecyclerView的行的布局在item_row.xml中定义,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="8dp"
app:cardUseCompatPadding="true">
<TextView
android:id="@+id/tvItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Item X"
</android.support.v7.widget.CardView>
下面给出了RecyclerViewAdapter.java类的代码。
package com.theitroad.androidrecyclerviewlayoutanimation;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemViewHolder> {
List<String> itemList;
public RecyclerViewAdapter(List<String> itemList) {
this.itemList = itemList;
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_row, viewGroup, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder myViewHolder, int position) {
myViewHolder.tvItem.setText(itemList.get(position));
}
@Override
public int getItemCount() {
return itemList == null ? 0 : itemList.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
TextView tvItem;
public ItemViewHolder(@NonNull View itemView) {
super(itemView);
tvItem = itemView.findViewById(R.id.tvItem);
}
}
}
下面给出了MainActivity.java类的代码:
package com.theitroad.androidrecyclerviewlayoutanimation;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.GridLayoutAnimationController;
import android.view.animation.LayoutAnimationController;
import android.widget.Spinner;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
FloatingActionButton fab;
RecyclerView recyclerView;
RecyclerViewAdapter recyclerViewAdapter;
ArrayList<String> arrayList = new ArrayList<>();
int[] animationList = {R.anim.layout_animation_up_to_down, R.anim.layout_animation_right_to_left, R.anim.layout_animation_down_to_up, R.anim.layout_animation_left_to_right};
int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fab = findViewById(R.id.fab);
recyclerView = findViewById(R.id.recyclerView);
populateData();
initAdapter();
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (i < animationList.length - 1) {
i++;
} else {
i = 0;
}
runAnimationAgain();
}
});
}
private void populateData() {
for (int i = 0; i < 12; i++) {
arrayList.add("Item " + i);
}
}
private void initAdapter() {
recyclerViewAdapter = new RecyclerViewAdapter(arrayList);
recyclerView.setAdapter(recyclerViewAdapter);
}
private void runAnimationAgain() {
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(this, animationList[i]);
recyclerView.setLayoutAnimation(controller);
recyclerViewAdapter.notifyDataSetChanged();
recyclerView.scheduleLayoutAnimation();
}
}
runAnimationAgain方法用于遍历每个动画,然后在RecyclerView上再次运行它们。
上面应用程序的输出如下:
现在,如果我们将GridLayoutManager用作布局管理器,我们将获得以下输出:
recyclerView.setLayoutManager(new GridLayoutManager(this,2,GridLayoutManager.VERTICAL,false));
上面的布局动画不是网格布局动画。
一次对每一行进行动画处理。
这是不正确的。
RecyclerView LayoutAnimation仅默认用于列表。
为了执行Grid Layout Animation,我们需要自定义回收者视图。

