12/08/2018, 16:48

Làm thế nào để bổ sung tính năng Item Click cho RecyclerView ?

Trước tiên , cho những ai chưa biết Recycler View là gì , mình xin trích dẫn từ tài liệu "danh môn chính phái" của Google Developer Widget RecyclerView là một phiên bản nâng cao và linh hoạt hơn của ListView. Widget này là một bộ chứa để hiển thị các tập dữ liệu lớn có thể được cuộn rất hiệu ...

Trước tiên , cho những ai chưa biết Recycler View là gì , mình xin trích dẫn từ tài liệu "danh môn chính phái" của Google Developer

Widget RecyclerView là một phiên bản nâng cao và linh hoạt hơn của ListView. Widget này là một bộ chứa để hiển thị các tập dữ liệu lớn có thể được cuộn rất hiệu quả bằng cách duy trì một số dạng xem hữu hạn. Sử dụng widget RecyclerView khi bạn có các bộ sưu tập dữ liệu với phần tử thay đổi vào thời gian chạy dựa vào hành động của người dùng hoặc sự kiện mạng.

Ok , đọc sơ qua vậy chúng ta tạm hiểu là RecyclerView là 1 biến thể của ListView , nhưng được nâng cấp trở nên linh hoạt hơn , mạnh mẽ hơn nhiều.

Nhưng có cái trắc trở là , hoặc có thể kiến thức của mình hạn hẹp , không thấy bổ sung sự kiện OnItemClickListener , mà cái đó là vô cùng cần thiết , giả sử có 1 danh sách mà muốn tap vào để xem chi tiết thì chịu sao ?

Không sao , trong bài hướng dẫn nhỏ này , mình xin chia sẻ với các bạn 1 tips

Đầu tiên , tạo 1 dự án , add Support Design library vào gradle , trong này có cả RecyclerView rồi , nếu muốn gọn nhẹ thì cài library Recycler riêng

Tiếp theo , add RecyclerView vào activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_awidth="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="edmt.dev.androidrecyclerviewclick.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_awidth="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Xong rồi , chúng ta hãy tạo 1 file layout_item_recyclerview.xml để custom cái giao diện của item hiển thị trong RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_awidth="match_parent"
    android:padding="20dp"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/txtDescription"
        android:text="Description"
        android:textColor="#000"
        android:textSize="20sp"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Vậy là ta đã xong phần vỏ , giờ là phần ruột nè , tạo 1 interface đặt tên là "ItemClickListener"

public interface ItemClickListener {
    void onClick(View view, int position,boolean isLongClick);
}

Và tất nhiên , RecyclerView không thể thiếu RecyclerView.Adapter được , mà thằng RecyclerView.Adapter lại không thể thiếu Recycler.ViewHolder được , ta phải tạo 2 thằng này luôn Tạo lớp RecyclerAdapter

package edmt.dev.androidrecyclerviewclick;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by reale on 2/22/2017.
 */

class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener
{
    public TextView txt_description;

    private ItemClickListener itemClickListener;

    public RecyclerViewHolder(View itemView) {
        super(itemView);
        txt_description = (TextView)itemView.findViewById(R.id.txtDescription);

        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
    }

    public void setItemClickListener(ItemClickListener itemClickListener)
    {
        this.itemClickListener = itemClickListener;
    }

    @Override
    public void onClick(View v) {
            itemClickListener.onClick(v,getAdapterPosition(),false);
    }

    @Override
    public boolean onLongClick(View v) {
        itemClickListener.onClick(v,getAdapterPosition(),true);
        return true;
    }
}
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerViewHolder> {

    private List<String> listData = new ArrayList<>();
    private Context context;

    public RecyclerAdapter(List<String> listData, Context context) {
        this.listData = listData;
        this.context = context;
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.layout_item_recycler_view,parent,false);

        return new RecyclerViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        holder.txt_description.setText(listData.get(position));

        holder.setItemClickListener(new ItemClickListener() {
            @Override
            public void onClick(View view, int position, boolean isLongClick) {
                if(isLongClick)
                    Toast.makeText(context, "Long Click: "+listData.get(position), Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(context, " "+listData.get(position), Toast.LENGTH_SHORT).show();
            }
        });
    }

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

Trong lớp này , chỉ cần chú ý đoạn này

lass RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener // Implement 2 sự kiện onClick và onLongClick
{
    public TextView txt_description; // Khai báo biến 

    private ItemClickListener itemClickListener; // Khai báo interface

    public RecyclerViewHolder(View itemView) {
        super(itemView);
        txt_description = (TextView)itemView.findViewById(R.id.txtDescription); // tiến hành tìm view và assign địa chỉ

        itemView.setOnClickListener(this); // Mấu chốt ở đây , set sự kiên onClick cho View
        itemView.setOnLongClickListener(this); // Mấu chốt ở đây , set sự kiên onLongClick cho View
    }

   //Tạo setter cho biến itemClickListenenr
    public void setItemClickListener(ItemClickListener itemClickListener)
    {
        this.itemClickListener = itemClickListener;
    }

    @Override
    public void onClick(View v) {
            itemClickListener.onClick(v,getAdapterPosition(),false); // Gọi interface , false là vì đây là onClick
    }

    @Override
    public boolean onLongClick(View v) {
        itemClickListener.onClick(v,getAdapterPosition(),true); // Gọi interface , true là vì đây là onLongClick
        return true;
    }
}

Ở trên ta có thể hiểu là , khi ViewHolder được gọi , nó sẽ inflate cái layout_item_recyclerview của chúng ta và chúng ta lợi dụng điểm này để set sự kiện onClick và onLongClick (nếu cần) cho nó

Sau đó , ở phương thức onBindViewHolder() của Adapter , chúng ta tiến hành hiện thực sự kiện onClick hoặc onLongClick

@Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        holder.txt_description.setText(listData.get(position));

        holder.setItemClickListener(new ItemClickListener() {
            @Override
            public void onClick(View view, int position, boolean isLongClick) {
                if(isLongClick)
                    Toast.makeText(context, "Long Click: "+listData.get(position), Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(context, " "+listData.get(position), Toast.LENGTH_SHORT).show();
            }
        });
    }

Okay , và ở MainActivity ta chỉ việc code

package edmt.dev.androidrecyclerviewclick;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private RecyclerView.LayoutManager layoutManager;
    private List<String> listData = new ArrayList<>();

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

        setupList();

        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        RecyclerAdapter adapter = new RecyclerAdapter(listData,this);
        recyclerView.setAdapter(adapter);

    }

    private void setupList() {
        for(int i = 1;i<=10;i++)
            listData.add("Click me "+i);
    }
}

Và kết quả :

Và các bạn có thể tha hồ mà replace Toast message với code của các bạn , có thể là chuyển activity , có thể xóa item... tùy ý

Chúc các bạn thành công

0