Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng CardView trong RecyclerView trên Android

Giới thiệu

CardView là container có góc bo tròn, shadow (đổ bóng), elevation - tạo giao diện Material Design đẹp mắt cho item RecyclerView.

Các bước thực hiện

Bước 1: Dependency (build.gradle)

dependencies {
    implementation "androidx.recyclerview:recyclerview:1.3.0"
    implementation "androidx.cardview:cardview:1.0.0"
    implementation "com.google.android.material:material:1.9.0"
}

Bước 2: Giao diện chính (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    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="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:title="CardView RecyclerView" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Bước 3: Item Layout - CardView (res/layout/item_card.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.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"
    android:layout_margin="8dp"
    app:cardCornerRadius="12dp"
    app:cardElevation="4dp"
    app:cardUseCompatPadding="true"
    app:cardBackgroundColor="@android:color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center"
        android:padding="16dp">

        <ImageView
            android:id="@+id/ivIcon"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:src="@mipmap/ic_launcher"
            android:contentDescription="@string/app_name" />

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:gravity="center"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/tvSubtitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:gravity="center"
            android:text="Sairamkrishan"
            android:textSize="14sp"
            android:textColor="?android:attr/textColorSecondary" />

    </LinearLayout>

</androidx.cardview.widget.CardView>

Bước 4: Adapter (src/CardAdapter.java)

package com.example.myapplication;

import android.content.Context;
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.ImageView;
import android.widget.TextView;
import java.util.List;

public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {

    private List<String> titles;
    private OnItemClickListener listener;

    public interface OnItemClickListener {
        void onItemClick(int position);
    }

    public CardAdapter(List<String> titles, OnItemClickListener listener) {
        this.titles = titles;
        this.listener = listener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_card, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.tvTitle.setText(titles.get(position));
        holder.itemView.setOnClickListener(v -> {
            if (listener != null) listener.onItemClick(position);
        });
    }

    @Override
    public int getItemCount() {
        return titles.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView ivIcon;
        TextView tvTitle, tvSubtitle;
        ViewHolder(View view) {
            super(view);
            ivIcon = view.findViewById(R.id.ivIcon);
            tvTitle = view.findViewById(R.id.tvTitle);
            tvSubtitle = view.findViewById(R.id.tvSubtitle);
        }
    }
}

Bước 5: MainActivity.java

package com.example.myapplication;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements CardAdapter.OnItemClickListener {

    RecyclerView recyclerView;
    CardAdapter adapter;
    List<String> titles = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        for (int i = 1; i <= 20; i++) {
            titles.add("Item " + i);
        }

        adapter = new CardAdapter(titles, this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(int position) {
        // Xử lý click
    }
}

Tùy chỉnh CardView

AttributeMô tảGiá trị mẫu
app:cardCornerRadiusBo góc12dp, 16dp
app:cardElevationĐộ nâng (shadow)4dp, 8dp
app:cardUseCompatPaddingPadding tương thích API cũtrue
app:cardBackgroundColorMàu nền card@android:color/white
app:cardPreventCornerOverlapNgăn content đè lên góc botrue/false
app:cardMaxElevationMax elevation khi pressed8dp

Chạy ứng dụng

Nhấn Run. Danh sách hiển thị các CardView có shadow, góc bo tròn, cuộn mượt, Toolbar ẩn/hiện.

Cách sử dụng CardView trong RecyclerView trên Android

Best Practices

  • Dùng cardUseCompatPadding="true" để shadow hiển thị nhất quán trên API < 21.
  • Không lạm dụng elevation quá cao (>8dp) - gây lag khi cuộn.
  • Kết hợp với DiffUtil/ListAdapter cho cập nhật hiệu quả.
  • Item click: Dùng android:foreground="?attr/selectableItemBackground" trên CardView cho ripple effect.
  • Nesting: Tránh lồng CardView trong CardView.

CardView vs MaterialCardView (Material Components 1.2+)

<com.google.android.material.card.MaterialCardView
    ...
    app:strokeWidth="1dp"
    app:strokeColor="@color/divider"
    app:checkedIcon="@drawable/ic_check" />

MaterialCardView kế thừa CardView, thêm: stroke, checkable state, ripple tích hợp, tuân thủ Material Design 2/3.