RecyclerView में आइटम सिलेक्शन हाईलाइटिंग - सही तरीका
यह ट्यूटोरियल दिखाता है कि कैसे RecyclerView में सिंगल/मल्टी सिलेक्शन को सही ढंग से इम्प्लीमेंट किया जाता है, SparseBooleanArray और स्टेट-लिस्ट ड्रॉएबल का उपयोग करके।
चरण 1: निर्भरताएं
dependencies {
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.cardview:cardview:1.0.0"
}
चरण 2: सेलेक्टर ड्रॉएबल (हाईलाइट के लिए)
res/drawable/background_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
<!-- चुना गया स्टेट -->
<item android:state_activated="true"
android:drawable="@color/colorAccent" />
<!-- दबाया गया स्टेट -->
<item android:state_pressed="true"
android:drawable="@color/colorPrimaryLight" />
<!-- फोकस्ड स्टेट -->
<item android:state_focused="true"
android:drawable="@color/colorPrimaryLight" />
<!-- डिफॉल्ट -->
<item android:drawable="@android:color/white" />
</selector>
res/drawable/line_divider.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:height="1dp" />
<solid android:color="@color/colorPrimaryDark" />
</shape>
चरण 3: आइटम लेआउट
res/layout/list_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_selector"
android:padding="16dp">
<TextView
android:id="@+id/awardTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="पुरस्कार शीर्षक"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/awardYear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/awardTitle"
android:layout_alignStart="@id/awardTitle"
android:layout_marginTop="8dp"
android:text="वर्ष"
android:textColor="#666666" />
<TextView
android:id="@+id/playerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="खिलाड़ी नाम" />
</RelativeLayout>
चरण 4: डेटा मॉडल
src/ItemObject.java:
package com.app.sample;
public class ItemObject {
private String awardTitle;
private String awardYear;
private String player;
public ItemObject(String awardTitle, String awardYear, String player) {
this.awardTitle = awardTitle;
this.awardYear = awardYear;
this.player = player;
}
public String getAwardTitle() { return awardTitle; }
public String getAwardYear() { return awardYear; }
public String getPlayer() { return player; }
}
चरण 5: ViewHolder में क्लिक हैंडलिंग
src/RecyclerViewHolders.java:
package com.app.sample;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView awardTitle, awardYear, player;
private SparseBooleanArray selectedItems = new SparseBooleanArray();
private OnItemClickListener listener;
RecyclerViewHolders(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
awardTitle = itemView.findViewById(R.id.awardTitle);
awardYear = itemView.findViewById(R.id.awardYear);
player = itemView.findViewById(R.id.playerName);
}
void bind(ItemObject item, boolean isSelected) {
awardTitle.setText("पुरस्कार: " + item.getAwardTitle());
awardYear.setText("वर्ष: " + item.getAwardYear());
player.setText("खिलाड़ी: " + item.getPlayer());
// महत्वपूर्ण: एक्टिवेटेड स्टेट सेट करें (सेलेक्टर के लिए)
itemView.setActivated(isSelected);
}
@Override
public void onClick(View view) {
if (listener != null) {
listener.onItemClick(getAdapterPosition(), view);
}
}
void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
interface OnItemClickListener {
void onItemClick(int position, View view);
}
}
चरण 6: एडाप्टर में सिलेक्शन लॉजिक
src/RecyclerViewAdapter.java:
package com.app.sample;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {
private List<ItemObject> itemList;
private SparseBooleanArray selectedItems = new SparseBooleanArray();
private boolean multiSelect = false; // true = मल्टी-सिलेक्शन, false = सिंगल
private RecyclerViewHolders.OnItemClickListener clickListener;
public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
this.itemList = itemList;
}
public void setMultiSelect(boolean multiSelect) {
this.multiSelect = multiSelect;
}
public void setOnItemClickListener(RecyclerViewHolders.OnItemClickListener listener) {
this.clickListener = listener;
}
@NonNull
@Override
public RecyclerViewHolders onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_layout, parent, false);
RecyclerViewHolders holder = new RecyclerViewHolders(layoutView);
holder.setOnItemClickListener((pos, view) -> {
toggleSelection(pos);
if (clickListener != null) clickListener.onItemClick(pos, view);
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewHolders holder, int position) {
boolean isSelected = selectedItems.get(position, false);
holder.bind(itemList.get(position), isSelected);
}
@Override
public int getItemCount() {
return itemList.size();
}
private void toggleSelection(int position) {
if (multiSelect) {
if (selectedItems.get(position, false)) {
selectedItems.delete(position);
} else {
selectedItems.put(position, true);
}
} else {
// सिंगल सिलेक्शन: पहले क्लियर करें
selectedItems.clear();
selectedItems.put(position, true);
}
notifyDataSetChanged(); // या notifyItemChanged के लिए बेहतर परफॉरमेंस
}
public List<Integer> getSelectedPositions() {
List<Integer> positions = new ArrayList<>();
for (int i = 0; i < selectedItems.size(); i++) {
if (selectedItems.valueAt(i)) {
positions.add(selectedItems.keyAt(i));
}
}
return positions;
}
public void clearSelection() {
selectedItems.clear();
notifyDataSetChanged();
}
}
चरण 7: ItemDecoration (डिवाइडर)
src/SimpleItemDecoration.java:
package com.app.sample;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
class SimpleItemDecoration extends RecyclerView.ItemDecoration {
private Drawable drawable;
SimpleItemDecoration(Context context) {
drawable = ContextCompat.getDrawable(context, R.drawable.line_divider);
}
@Override
public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + drawable.getIntrinsicHeight();
drawable.setBounds(left, top, right, bottom);
drawable.draw(canvas);
}
}
}
चरण 8: MainActivity
src/MainActivity.java:
package com.app.sample;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.addItemDecoration(new SimpleItemDecoration(this));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<ItemObject> items = getSampleData();
adapter = new RecyclerViewAdapter(this, items);
adapter.setMultiSelect(true); // या false सिंगल के लिए
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener((pos, view) -> {
// सिलेक्शन बदलने पर UI अपडेट
updateSelectionUI();
});
}
private List<ItemObject> getSampleData() {
List<ItemObject> items = new ArrayList<>();
items.add(new ItemObject("Ballon d'Or", "2007", "रिकार्डो काका"));
items.add(new ItemObject("Ballon d'Or", "2008", "क्रिस्टियानो रोनाल्डो"));
items.add(new ItemObject("Ballon d'Or", "2009-2012, 2015", "लियोनेल मेसी"));
items.add(new ItemObject("Ballon d'Or", "2013, 2014, 2016, 2017", "क्रिस्टियानो रोनाल्डो"));
items.add(new ItemObject("Ballon d'Or", "2018", "लुका मोड्रिक"));
items.add(new ItemObject("Ballon d'Or", "2019", "अभी तय नहीं"));
return items;
}
private void updateSelectionUI() {
// टूलबार में चुने गए आइटम्स की संख्या दिखाएं, आदि
}
}
चरण 9: मैनिफेस्ट
स्टैंडर्ड कॉन्फ़िगरेशन।
एडवांस्ड: ActionMode के साथ कॉन्टेक्स्टुअल एक्शन बार (CAB)
// MainActivity में
private ActionMode actionMode;
adapter.setOnItemClickListener((pos, view) -> {
if (actionMode == null) {
actionMode = startSupportActionMode(new ActionMode.Callback() {
@Override public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.context_menu, menu);
return true;
}
@Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.action_delete) {
deleteSelectedItems();
mode.finish();
return true;
}
return false;
}
@Override public void onDestroyActionMode(ActionMode mode) {
adapter.clearSelection();
actionMode = null;
}
});
}
updateActionModeTitle();
});
private void updateActionModeTitle() {
if (actionMode != null) {
actionMode.setTitle(adapter.getSelectedPositions().size() + " चुना गया");
}
}
बेस्ट प्रैक्टिसेज
setActivated()उपयोग करेंsetSelected()के बजाय - यह एक्सेसिबिलिटी और सेलेक्टर के साथ बेहतर काम करता हैSparseBooleanArrayउपयोग करें चुने गए पोजीशन्स ट्रैक करने के लिए - मेमोरी एफिशिएंटnotifyItemChanged()उपयोग करेंnotifyDataSetChanged()के बजाय एनिमेशन के लिए- मल्टी-सिलेक्शन के लिए लॉन्ग-प्रेस से शुरू करें, फिर सिंगल टैप
- चुने गए आइटम्स की गिनती टूलबार/एक्शनमोड में दिखाएं