Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีดึง Item ที่คลิกและ Position ใน RecyclerView

ตัวอย่างนี้สาธิตวิธี ดึง Item ที่คลิกและ Position ใน RecyclerView

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่ใน Android Studio

ไปที่ File → New Project และกรอกรายละเอียดที่จำเป็นทั้งหมด

ขั้นตอนที่ 2: เพิ่มโค้ดใน res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.v7.widget.Toolbar
            android:id="@+id/appbarlayout_tool_bar"
            android:background="@color/colorPrimary"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|snap|enterAlways"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

ขั้นตอนที่ 3: เพิ่มโค้ดใน src/MainActivity.java

package com.example.myapplication;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    TextView text;
    ArrayList<String> list = new ArrayList<>();
    private RecyclerView recyclerView;
    private CustomAdapter mAdapter;
    private OnClickInterface onClickInterface;

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.appbarlayout_tool_bar);
        toolbar.setTitle("This is toolbar.");
        setSupportActionBar(toolbar);

        onClickInterface = new OnClickInterface() {
            @Override
            public void setClick(int abc) {
                String clickedItem = list.get(abc); // ดึง Item จาก Position
                list.remove(abc);
                Toast.makeText(MainActivity.this, "Position: " + abc + ", Item: " + clickedItem, Toast.LENGTH_LONG).show();
                mAdapter.notifyDataSetChanged();
            }
        };

        recyclerView = findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter = new CustomAdapter(this, list, onClickInterface);
        recyclerView.setAdapter(mAdapter);
        recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));

        // ข้อมูลทดสอบ
        for (int i = 0; i < 5; i++) {
            list.add("sairamm");
            list.add("Krishna");
            list.add("prasad");
        }
    }
}

ขั้นตอนที่ 4: สร้าง CustomAdapter.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.TextView;
import java.util.ArrayList;

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {
    Context context;
    ArrayList<String> list;
    OnClickInterface onClickInterface;

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title;
        public MyViewHolder(View view) {
            super(view);
            title = view.findViewById(R.id.title);
        }
    }

    public CustomAdapter(Context context, ArrayList<String> list, OnClickInterface onClickInterface) {
        this.context = context;
        this.list = list;
        this.onClickInterface = onClickInterface;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, viewGroup, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, final int i) {
        myViewHolder.title.setText(list.get(i));
        myViewHolder.title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickInterface.setClick(i); // ส่ง Position กลับ
            }
        });
    }

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

ขั้นตอนที่ 5: เพิ่มโค้ดใน res/layout/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:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardElevation="10dp"
    app:cardCornerRadius="20dp"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/logo" />
        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="30sp" />
        <TextView
            android:id="@+id/textview2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Sairamkrishan"
            android:textSize="30sp" />
    </LinearLayout>
</android.support.v7.widget.CardView>

ขั้นตอนที่ 6: สร้าง Interface OnClickInterface

package com.example.myapplication;

public interface OnClickInterface {
    void setClick(int abc);
}

การทดสอบแอปพลิเคชัน

รันแอปพลิเคชันบนอุปกรณ์ Android จริง ใน Android Studio คลิกไอคอน Run เลือกอุปกรณ์ แล้วตรวจสอบหน้าจอเริ่มต้น

วิธีดึง Item ที่คลิกและ Position ใน RecyclerView

คลิกที่ TextView จะแสดง Position และ Item ที่คลิก

วิธีดึง Item ที่คลิกและ Position ใน RecyclerView

รูปแบบการจัดการ Click ใน RecyclerView (Pattern Comparison)

Pattern คำอธิบาย ข้อดี ข้อเสีย
Interface Callback (ตัวอย่างนี้) Adapter รับ Interface, ViewHolder เรียก Callback แยก Logic, ทดสอบง่าย, Reusable Boilerplate เยอะ (Java)
Lambda/Kotlin ส่ง Lambda เข้า Adapter Constructor โค้ดสั้น, อ่านง่าย ต้องใช้ Kotlin หรือ Java 8+
View.OnClickListener ใน ViewHolder ViewHolder implement OnClickListener เอง ไม่ต้องสร้าง Interface แยก Logic ผูกกับ ViewHolder ยากต่อการทดสอบ
ItemTouchHelper สำหรับ Swipe/Drag Built-in Animation, UX ดี ไม่ใช่สำหรับ Click ธรรมดา
RecyclerView.OnItemTouchListener Low-level Touch Interceptor ควบคุมได้ทุกอย่าง ซับซ้อน, Overkill สำหรับ Click ธรรมดา

Best Practice: ใช้ getBindingAdapterPosition() (API 28+)

// ใน ViewHolder (แทนการส่ง position ผ่าน parameter)
myViewHolder.itemView.setOnClickListener(v -> {
    int position = myViewHolder.getBindingAdapterPosition();
    if (position != RecyclerView.NO_POSITION) {
        onClickInterface.setClick(position);
    }
});

เหตุผล: Position ใน onBindViewHolder อาจล้าสมัย (Stale) หากมีการ Insert/Remove ระหว่าง Render