In this tutorial, we’ll learn how to create animation for a RecyclerView in which elements are displayed in the form of a Grid.
在本教程中,我们将学习如何为RecyclerView创建动画,其中的元素以Grid形式显示。
We’ve already discussed RecyclerView Layout Animations earlier using a List.
我们之前已经使用列表讨论了RecyclerView布局动画 。
RecyclerView网格动画 (RecyclerView Grid Animation)
In the previous tutorial, we created List based Layout Animations. At the end of the tutorial, we applied them to a Grid Layout and saw that the animation is still list based on the grid instead of row and column based.
在上一教程中,我们创建了基于列表的布局动画。 在本教程的最后,我们将它们应用于“网格布局”,发现动画仍然是基于网格的列表,而不是基于行和列的列表。
In order to show Grid-based animation we need to use <gridlayoutanimation
tag.
But this won’t work on a normal RecyclerView. It will crash since by default a RecyclerView doesn’t know anything about how the elements are placed by the Layout Manager and assumes a list based placement.
为了显示基于网格的动画,我们需要使用<gridlayoutanimation
标签。
但这在正常的RecyclerView上不起作用。 它将崩溃,因为默认情况下,RecyclerView对布局管理器如何放置元素一无所知,并假定基于列表的放置方式。
Hence we need to create a custom RecyclerView first, overriding the important methods.
因此,我们需要首先创建一个自定义的RecyclerView,以覆盖重要的方法。
Let’s get started with our application.
让我们开始使用我们的应用程序。
项目结构 (Project Structure)
码 (Code)
The code for the CustomGridRecyclerView.java
class is given below:
下面给出CustomGridRecyclerView.java
类的代码:
package com.journaldev.androidrecyclerviewgridlayoutanimations;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.GridLayoutAnimationController;
public class CustomGridRecyclerView extends RecyclerView {
public CustomGridRecyclerView(Context context) {
super(context);
}
public CustomGridRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomGridRecyclerView(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("This recyclerview should use grid layout manager as the layout manager");
}
}
@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);
}
}
}
In the above code, we’ve explicitly set the RecyclerView to use grids row and columns for animating.
在上面的代码中,我们明确设置了RecyclerView以使用网格行和列进行动画处理。
The code for the activity_main.xml 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">
<com.journaldev.androidrecyclerviewgridlayoutanimations.CustomGridRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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>
The code for the MainActivity.java is given below:
MainActivity.java的代码如下:
package com.journaldev.androidrecyclerviewgridlayoutanimations;
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.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.widget.GridLayout;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
CustomGridRecyclerView recyclerView;
RecyclerViewAdapter recyclerViewAdapter;
FloatingActionButton fab;
ArrayList<String> arrayList = new ArrayList<>();
@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) {
runAnimationAgain();
}
});
}
private void populateData() {
for (int i = 0; i < 20; i++) {
arrayList.add("Item " + i);
}
}
private void initAdapter() {
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
recyclerViewAdapter = new RecyclerViewAdapter(arrayList);
recyclerView.setAdapter(recyclerViewAdapter);
}
private void runAnimationAgain() {
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(this, R.anim.gridlayout_animation_from_bottom);
recyclerView.setLayoutAnimation(controller);
recyclerViewAdapter.notifyDataSetChanged();
recyclerView.scheduleLayoutAnimation();
}
}
The animation set is defined in the anim
folder in the file down_to_up.xml
.
动画集在文件down_to_up.xml
的anim
文件夹中定义。
<?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>
The grid layout animation is defined in the file: gridlayout_animation_from_bottom.xml
.
网格布局动画在以下文件中定义: gridlayout_animation_from_bottom.xml
。
<?xml version="1.0" encoding="utf-8"?>
<gridLayoutAnimation xmlns:android="https://schemas.android.com/apk/res/android"
android:animation="@anim/down_to_up"
android:animationOrder="normal"
android:columnDelay="15%"
android:direction="top_to_bottom|left_to_right"
android:rowDelay="15%"
android:startOffset="700" />
The row and column delay attributes are used to define the delay in animation in each row and column respectively after the previous row got animated.
行和列延迟属性用于在上一行获得动画之后分别定义每行和每列中动画的延迟。
The code for the RecyclerViewAdapter.java class is given below:
下面给出了RecyclerViewAdapter.java类的代码:
package com.journaldev.androidrecyclerviewgridlayoutanimations;
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 output of the above application in action is given below:
上面应用程序的输出如下:
That brings an end to this tutorial. You can download the complete project from the link below:
这样就结束了本教程。 您可以从下面的链接下载完整的项目:
翻译自: https://www.journaldev.com/24127/android-recyclerview-grid-layout-animations