Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Android

Android RecyclerView में चुने गए आइटम को सही तरीके से कैसे हाईलाइट करें?

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() के बजाय एनिमेशन के लिए
  • मल्टी-सिलेक्शन के लिए लॉन्ग-प्रेस से शुरू करें, फिर सिंगल टैप
  • चुने गए आइटम्स की गिनती टूलबार/एक्शनमोड में दिखाएं
  1. एंड्रॉइड में NestedScrollView के अंदर RecyclerView का उपयोग कैसे करें एंड्रॉइड में NestedScrollView के अंदर RecyclerView का उपयोग कैसे करें

    NestedScrollView में RecyclerView को सही तरीके से एम्बेड करना NestedScrollView के अंदर RecyclerView रखना एक सामान्य पैटर्न है (जैसे: प्रोफाइल स्क्रीन जिसमें हेडर + सूची हो)। मुख्य चुनौती स्क्रॉल संघर्ष और RecyclerView की ऊंचाई मापन है। आधुनिक एंड्रॉइड में setNestedScrollingEnabled(false) या nestedSc

  1. एंड्रॉइड में स्पिनर का चयनित आइटम मान द्वारा कैसे सेट करें एंड्रॉइड में स्पिनर का चयनित आइटम मान द्वारा कैसे सेट करें

    Spinner में पोजिशन के बजाय मान (वैल्यू) के आधार पर चयन सेट करना डिफ़ॉल्ट रूप से spinner.setSelection(position) इंडेक्स का उपयोग करता है। लेकिन अक्सर हमें किसी विशिष्ट मान (जैसे क्रिस्टियानो रोनाल्डो) के आधार पर चयन सेट करना होता है। यह उदाहरण मान-आधारित चयन के तरीके दिखाता है। चरण 1: नया प्रोजेक्ट

  1. Android TextView में टेक्स्ट को जस्टिफाई कैसे करें? Android TextView में टेक्स्ट को जस्टिफाई कैसे करें?

    यह उदाहरण दर्शाता है कि Android में TextView में टेक्स्ट को जस्टिफाई (दोनों किनारों पर अलाइन) कैसे किया जाता है। समस्या Android का स्टैंडर्ड TextView android:gravity=center_horizontal या left|right से जस्टिफिकेशन सपोर्ट नहीं करता। API 26 (Android 8.0) से android:justificationMode=inter_word उपलब्ध