In this tutorial, we’ll be discussing and implementing RecyclerView Layout Animations in our Android Application.
在本教程中,我们将在Android应用程序中讨论和实现RecyclerView布局动画。
Android RecyclerView布局动画 (Android RecyclerView Layout Animations)
There are many ways to Animate rows in a RecyclerView.
Two commonly tried and tested ways are :
在RecyclerView中可以使用多种方法对行进行动画处理。
两种常用的经过测试的方法是:
- Using ItemAnimators. – Read this tutorial. 使用ItemAnimators。 – 阅读本教程 。
- Setting animation on each row in the
onBindViewHolder
in the Adapter class 在Adapter类的onBindViewHolder
中的每一行上设置动画
There’s another lesser-known but more efficient way of animating a RecyclerView using Layout Animations.
还有另一种鲜为人知但更有效的使用Layout Animations为RecyclerView设置动画的方法 。
We can directly pass the animation resource asset in the XML on the attribute android:layoutAnimation
.
我们可以直接在属性android:layoutAnimation
上以XML形式传递动画资源资产。
layoutAnimation
is valid on all other layouts as well besides RecyclerView.
layoutAnimation
在除RecyclerView之外的所有其他布局上均有效。
Let’s start by defining some basic Animations in the res | anim
folder in our Android Studio Project.
让我们从在res | anim
Android Studio项目中的res | anim
文件夹。
down_to_up.xml
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
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
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
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>
Now let’s create the layoutAnimation
for each of these animation sets.
现在,我们为每个动画集创建layoutAnimation
。
layout_animation_down_to_up.xml
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
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
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
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和编程方式设置布局动画 (Setting Layout Animation in XML and Programmatically)
We can set the Layout Animation on RecyclerView in XML in the following way:
我们可以通过以下方式在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"
/>
Programmatically:
以编程方式:
int resId = R.anim.layout_animation_right_to_left;
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(context, resId);
recyclerView.setLayoutAnimation(animation);
In order to re-run the animation or in case the data set of the RecyclerView has changed the following code is used:
为了重新运行动画,或者在RecyclerView的数据集已更改的情况下,使用以下代码:
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_right_to_left);
recyclerView.setLayoutAnimation(controller);
recyclerView.getAdapter().notifyDataSetChanged();
recyclerView.scheduleLayoutAnimation();
项目结构 (Project Structure)
码 (Code)
The code for the activity_main.xml layout is given below:
下面给出了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 is used to toggle through the different layout animations.
FloatingActionButton用于切换不同的布局动画。
The layout for the rows of RecyclerView is defined in item_row.xml as shown below:
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>
The code for the RecyclerViewAdapter.java
class is given below.
下面给出了RecyclerViewAdapter.java
类的代码。
package com.journaldev.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);
}
}
}
The code for the MainActivity.java
class is given below:
MainActivity.java
类的代码如下:
package com.journaldev.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
method is used to loop through each animation and run them on the RecyclerView again.
runAnimationAgain
方法用于循环遍历每个动画,然后在RecyclerView上再次运行它们。
The output of the above application in action is given below:
上面应用程序的输出如下:
Now if we apply a GridLayoutManager as the layout manager we’ll get the following output:
现在,如果我们将GridLayoutManager用作布局管理器,我们将获得以下输出:
recyclerView.setLayoutManager(new GridLayoutManager(this,2,GridLayoutManager.VERTICAL,false));
The above layout animation is not grid layout animation. It’s animating each row at a time.
This is incorrect. The RecyclerView LayoutAnimation defaults for Lists only.
In order to do Grid Layout Animation, we need to customize the recycler view.
We’ll do that in the next tutorial.
上面的布局动画不是网格布局动画。 一次为每一行设置动画。
这是不正确的。 RecyclerView LayoutAnimation仅默认用于列表。
为了执行Grid Layout Animation,我们需要自定义回收者视图。
我们将在下一个教程中做到这一点。
That brings an end to this tutorial. You can download the project from the link below:
这样就结束了本教程。 您可以从下面的链接下载项目:
翻译自: https://www.journaldev.com/24088/android-recyclerview-layout-animations