Giới thiệu về RecyclerView và CardView
Trước khi đi vào ví dụ về animation cho item RecyclerView, chúng ta cần hiểu RecyclerView là gì. RecyclerView là phiên bản nâng cao của ListView, hoạt động dựa trên mẫu thiết kế ViewHolder. Nó cho phép hiển thị danh sách hoặc lưới các item một cách linh hoạt và hiệu quả.
CardView kế thừa từ FrameLayout, được dùng để hiển thị các item theo kiểu thẻ (card). Nó hỗ trợ sẵn các thuộc tính như góc bo tròn (radius) và đổ bóng (shadow).
Ví dụ này minh họa cách tích hợp animation vào RecyclerView kết hợp CardView bằng cách xây dựng một ứng dụng quản lý sinh viên đơn giản hiển thị tên và tuổi.
Các bước thực hiện
Bước 1: Tạo project mới
Mở Android Studio, chọn File → New Project và điền các thông tin cần thiết để tạo project mới.
Bước 2: Thêm thư viện dependency
Mở file build.gradle (Module: app) và thêm các thư viện RecyclerView và CardView:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.andy.tutorialspoint"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Bước 3: Cấu hình layout chính (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
Ở đây chúng ta đặt RecyclerView làm view con của RelativeLayout.
Bước 4: Code MainActivity.java
package com.example.andy.tutorialspoint;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private StudentAdapter studentAdapter;
private List<StudentData> studentDataList = new ArrayList<>();
@TargetApi(Build.VERSION_CODES.O)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
studentAdapter = new StudentAdapter(studentDataList, MainActivity.this);
RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(studentAdapter);
prepareStudentData();
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void prepareStudentData() {
studentDataList.add(new StudentData("Sai", 25));
studentDataList.add(new StudentData("Sai", 25));
studentDataList.add(new StudentData("Raghu", 20));
studentDataList.add(new StudentData("Raj", 28));
studentDataList.add(new StudentData("Amar", 15));
studentDataList.add(new StudentData("Bapu", 19));
studentDataList.add(new StudentData("Chandra", 52));
studentDataList.add(new StudentData("Deraj", 30));
studentDataList.add(new StudentData("Eshanth", 28));
// Sắp xếp danh sách theo tên
Collections.sort(studentDataList, new Comparator<StudentData>() {
@Override
public int compare(StudentData o1, StudentData o2) {
return o1.name.compareTo(o2.name);
}
});
}
}
Trong code trên, chúng ta khởi tạo RecyclerView, gán adapter và LayoutManager. Dữ liệu sinh viên được thêm vào ArrayList và sắp xếp theo tên sử dụng Collections.sort() với Comparator tùy chỉnh.
Bước 5: Tạo StudentAdapter.java với animation
package com.example.andy.tutorialspoint;
import android.content.Context;
import android.graphics.Color;
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.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
import java.util.Random;
class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.MyViewHolder> {
private List<StudentData> studentDataList;
private Context context;
private int lastPosition = -1;
public StudentAdapter(List<StudentData> studentDataList, Context context) {
this.studentDataList = studentDataList;
this.context = context;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.student_list_row, viewGroup, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder viewHolder, int i) {
StudentData data = studentDataList.get(i);
Random rnd = new Random();
int currentColor = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewHolder.parent.setBackgroundColor(currentColor);
viewHolder.name.setText(data.name);
viewHolder.age.setText(String.valueOf(data.age));
setAnimation(viewHolder.parent, i);
}
private void setAnimation(View viewToAnimate, int position) {
// Chỉ animate khi item chưa từng hiển thị trên màn hình
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
@Override
public int getItemCount() {
return studentDataList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView name, age;
LinearLayout parent;
public MyViewHolder(View itemView) {
super(itemView);
parent = itemView.findViewById(R.id.parent);
name = itemView.findViewById(R.id.name);
age = itemView.findViewById(R.id.age);
}
}
}
Giải thích các phương thức chính:
- onCreateViewHolder(): Tạo ViewHolder mới từ layout item.
- onBindViewHolder(): Gán dữ liệu vào ViewHolder. Tại đây cũng set màu nền ngẫu nhiên và gọi animation.
- getItemCount(): Trả về số lượng item.
- MyViewHolder: Inner class giữ reference các view con.
Tạo màu nền ngẫu nhiên:
Random rnd = new Random();
int currentColor = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewHolder.parent.setBackgroundColor(currentColor);
Logic animation trong setAnimation():
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
Chỉ animate các item mới xuất hiện (position > lastPosition), sử dụng animation có sẵn slide_in_left của Android.
Bước 6: Layout item (student_list_row.xml)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:card_view="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
card_view:cardCornerRadius="4dp"
android:id="@+id/card_view"
android:layout_margin="10dp"
android:layout_height="200dp">
<LinearLayout
android:id="@+id/parent"
android:layout_gravity="center"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:textColor="#FFF"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:textColor="#FFF"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
Mỗi item là một CardView chứa LinearLayout dọc với 2 TextView hiển thị tên và tuổi. CardView cung cấp góc bo tròn và đổ bóng tự động.
Bước 7: Model StudentData.java
package com.example.andy.tutorialspoint;
class StudentData {
String name;
int age;
public StudentData(String name, int age) {
this.name = name;
this.age = age;
}
}
Chạy ứng dụng
Kết nối thiết bị Android thật, chọn Run từ toolbar. Màn hình đầu tiên hiển thị danh sách sinh viên:

Khi cuộn xuống, các item mới sẽ xuất hiện với hiệu ứng trượt từ trái sang:
