Android RecyclerView इसके अलावा और वस्तुओं को हटाने


144

मेरे पास एक TextView टेक्स्ट बॉक्स और एक क्रॉस बटन ImageView के साथ एक RecyclerView है। मेरे पास recyclerview के बाहर एक बटन है जो क्रॉस बटन ImageView को दिखाई / गया है।

मैं recylerview से एक आइटम को हटाने के लिए देख रहा हूं, जब उस आइटम को क्रॉस बटन ImageView दबाया जाता है।

मेरा एडाप्टर:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {

    private ArrayList<String> mDataset;
    private static Context sContext;

    public MyAdapter(Context context, ArrayList<String> myDataset) {
        mDataset = myDataset;
        sContext = context;
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);

        ViewHolder holder = new ViewHolder(v);
        holder.mNameTextView.setOnClickListener(MyAdapter.this);
        holder.mNameTextView.setOnLongClickListener(MyAdapter.this);

        holder.mNameTextView.setTag(holder);

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        holder.mNameTextView.setText(mDataset.get(position));

    }

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


    @Override
    public void onClick(View view) {
        ViewHolder holder = (ViewHolder) view.getTag();
        if (view.getId() == holder.mNameTextView.getId()) {
            Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show();
        }
    }


    @Override
    public boolean onLongClick(View view) {
        ViewHolder holder = (ViewHolder) view.getTag();
        if (view.getId() == holder.mNameTextView.getId()) {
            mDataset.remove(holder.getPosition());

            notifyDataSetChanged();

            Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list",
                    Toast.LENGTH_SHORT).show();
        }
        return false;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mNumberRowTextView;
        public TextView mNameTextView;


        public ViewHolder(View v) {
            super(v);

            mNameTextView = (TextView) v.findViewById(R.id.nameTextView);
        }
    }
}

मेरा लेआउट है:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:id="@+id/layout">

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:padding="5dp"
        android:background="@drawable/greyline"/>

    <ImageView
        android:id="@+id/crossButton"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:visibility="gone"
        android:layout_marginLeft="50dp"
        android:src="@drawable/cross" />
</LinearLayout>

मैं अपने क्रॉसबटन इमेज व्यू के लिए ऑनक्लिक पर काम करने जैसा कुछ कैसे प्राप्त कर सकता हूं? क्या कोई बेहतर तरीका है? शायद एक आइटम को हटाने में पूरे आइटम को क्लिक करें? Recyclerview उन स्थानों की एक सूची दिखाता है जिन्हें संपादित करने की आवश्यकता है। किसी भी तकनीकी सलाह या सर्वोत्तम कार्यान्वयन पर टिप्पणी / सुझाव बेहद सराहना की जाएगी।


एक नजर लिंक 1 लिंक 2 देखिए इससे U
SaravanaRaja


1
आप इस उदाहरण को गितुब हैप्पी कोड में देख सकते हैं !!!!
काबिजस

जवाबों:


267

मैंने भी कुछ ऐसा ही किया है। अपने में MyAdapter:

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    public CardView mCardView;
    public TextView mTextViewTitle;
    public TextView mTextViewContent;
    public ImageView mImageViewContentPic;

    public ImageView imgViewRemoveIcon;
    public ViewHolder(View v) {
        super(v);
        mCardView = (CardView) v.findViewById(R.id.card_view);
        mTextViewTitle = (TextView) v.findViewById(R.id.item_title);
        mTextViewContent = (TextView) v.findViewById(R.id.item_content);
        mImageViewContentPic = (ImageView) v.findViewById(R.id.item_content_pic);
        //......
        imgViewRemoveIcon = (ImageView) v.findViewById(R.id.remove_icon);

        mTextViewContent.setOnClickListener(this);
        imgViewRemoveIcon.setOnClickListener(this);
        v.setOnClickListener(this);
        mTextViewContent.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                if (mItemClickListener != null) {
                    mItemClickListener.onItemClick(view, getPosition());
                }
                return false;
            }
        });
    }


    @Override
    public void onClick(View v) {
        //Log.d("View: ", v.toString());
        //Toast.makeText(v.getContext(), mTextViewTitle.getText() + " position = " + getPosition(), Toast.LENGTH_SHORT).show();
        if(v.equals(imgViewRemoveIcon)){
            removeAt(getPosition());
        }else if (mItemClickListener != null) {
            mItemClickListener.onItemClick(v, getPosition());
        }
    }
}

public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
    this.mItemClickListener = mItemClickListener;
}
public void removeAt(int position) {
    mDataset.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, mDataSet.size());
}

उम्मीद है की यह मदद करेगा।

संपादित करें:

getPosition()अब अपदस्थ है, getAdapterPosition()इसके बजाय उपयोग करें ।


50
notifyItemRangeChanged(getPosition, mDataSet.size());आइटम हटाने के बाद आप पैराडाइट के उत्तर को भी जोड़ना चाहेंगे ताकि हटाए गए आइटम के नीचे के सभी दृश्य तदनुसार समायोजित हो जाएं।
क्रिस एंजेल

3
मैं एक ही समस्या है, लेकिन getPosition()अब पदावनत है
चिप

4
धन्यवाद, जाहिरा तौर पर सिर्फ कॉल notifyItemRemoved(position)करना पर्याप्त नहीं था।
एकटॉस 974

3
@chip का उपयोग करें getAdapterPosition ()
टायलर Pfaff

2
जब आप आइटम को जल्दी से ऊपर और नीचे दोनों से हटाते हैं तो यह कोड एक समस्या को ठीक नहीं करता है।
विटो वलोव

60

सबसे पहले, आइटम को सूची से हटा दिया जाना चाहिए!

  mDataSet.remove(getAdapterPosition());

फिर:

  notifyItemRemoved(getAdapterPosition());
  notifyItemRangeChanged(getAdapterPosition(),mDataSet.size());

2
आपके ओवरमुक का धन्यवाद, मान लीजिए कि मुझे अधिक मान जोड़ने होंगे इसका मतलब मैं उसके लिए क्या कर सकता हूं।
मोहनराज एस

यह आपके एडॉप्टर में सूची के आकार से संबंधित है। @ हम्माद नासिर
ज़हरा

मैंने भी ऐसा ही किया, लेकिन पुनरावर्तन की ऊंचाई डायनेमिकली नहीं बदली। mNotes.remove (स्थिति); (स्थिति) notifyItemRemoved; InformItemRangeChanged (स्थिति, getItemCount ()); @ ज़हरा। मुझे कुछ याद नहीं आया।
हितेश धामनिया

22

अगर अभी भी आइटम नहीं हटाया इस जादू विधि का उपयोग :)

private void deleteItem(int position) {
        mDataSet.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, mDataSet.size());
        holder.itemView.setVisibility(View.GONE);
}

कोटलिन संस्करण

private fun deleteItem(position: Int) {
    mDataSet.removeAt(position)
    notifyItemRemoved(position)
    notifyItemRangeChanged(position, mDataSet.size)
    holder.itemView.visibility = View.GONE
}

@ मोस्तफा: मान लीजिए कि मेरे पास 10 आइटम हैं और मैं उस परिदृश्य में धारक को हटाता हूं। itemView.setVisibility (View.GONE), सभी डेटा छिपाएं,
हितेश धम्शनिया

@HiteshDhamshaniya नहीं, यह सिर्फ छिपा है और अंतिम दृश्य चला गया है
मुस्तफा अन्टर

नजरिया छुपाने की जरूरत नहीं। dataSet.remove (स्थिति) ठीक काम करता है, लेकिन yoi को InformDatasetChamged () या InformItemRemoved (डेटासेट। size () - 1) को कॉल करने की आवश्यकता है
Karue Benson Karue

धारक के लिए धन्यवाद। itemView.setVisibility (View.GONE);
होइव

10

संकट

RecyclerViewडिफ़ॉल्ट रूप से, आपके डेटासेट में परिवर्तन से अनजान है। इसका मतलब यह है कि जब भी आप अपनी डेटा-सूची पर कोई विलोपन / जोड़ बनाते हैं, तो वे परिवर्तन सीधे आपके RecyclerView में दिखाई नहीं देंगे।

उपाय

RecyclerView आपको अपने डेटासेट स्थिति को साझा करने के लिए कुछ तरीके प्रदान करता है। ऐसा इसलिए होता है क्योंकि आपके डेटासेट में संशोधन से दृश्य परिवर्तन नहीं होता है, और इसके विपरीत। मानक एंड्रॉइड एपीआई आपको दृश्य हटाने की प्रक्रिया के साथ डेटा हटाने की प्रक्रिया (प्रश्न के उद्देश्य के लिए) को बांधने की अनुमति देता है ।

notifyItemChanged(index: Int)
notifyItemInserted(index: Int)
notifyItemRemoved(index: Int)
notifyItemRangeChanged(startPosition: Int, itemCount: Int)
notifyItemRangeInserted(startPosition: Int, itemCount: Int)
notifyItemRangeRemoved(startPosition: Int, itemCount: Int)

सर्वश्रेष्ठ दृष्टिकोण

यदि आप ठीक से निर्दिष्ट नहीं करते हैं कि आपके जोड़ / आइटम को हटाने पर क्या होता है (विचारों के बारे में बात करना), तो सूची के चारों ओर विभिन्न विचारों को स्थानांतरित करने के तरीके के बारे में जानकारी की कमी के कारण, RecyclerView बच्चे अनपेक्षित रूप से एनिमेटेड हैं।

इसके बजाय, निम्न कोड ठीक उसी तरह एनीमेशन को चलाएगा, जिस बच्चे को हटाया जा रहा है (और एक साइड नोट के रूप में, मेरे लिए यह किसी भी IndexOutOfBoundExceptions को ठीक करता है, स्टैकट्रेस द्वारा "डेटा असंगतता" के रूप में चिह्नित)

void remove(position: Int) {
    dataset.removeAt(position)
    notifyItemChanged(position)
    notifyItemRangeRemoved(position, 1)
}

हुड के तहत, अगर हम देखते हैं कि हम RecyclerViewयह समझाते हुए दस्तावेज़ पा सकते हैं कि हमें जो दूसरा पैरामीटर पास करना है, वह डेटासेट से निकाली गई वस्तुओं की संख्या है , न कि वस्तुओं की कुल संख्या (जैसा कि कुछ अन्य सूचना स्रोतों में गलत तरीके से कहा गया है)।

    /**
     * Notify any registered observers that the <code>itemCount</code> items previously
     * located at <code>positionStart</code> have been removed from the data set. The items
     * previously located at and after <code>positionStart + itemCount</code> may now be found
     * at <code>oldPosition - itemCount</code>.
     *
     * <p>This is a structural change event. Representations of other existing items in the data
     * set are still considered up to date and will not be rebound, though their positions
     * may be altered.</p>
     *
     * @param positionStart Previous position of the first item that was removed
     * @param itemCount Number of items removed from the data set
     */
    public final void notifyItemRangeRemoved(int positionStart, int itemCount) {
        mObservable.notifyItemRangeRemoved(positionStart, itemCount);
    }

7

संभवतः एक डुप्लिकेट उत्तर लेकिन मेरे लिए काफी उपयोगी है। आप नीचे दी गई विधि को लागू RecyclerView.Adapter<RecyclerView.ViewHolder> कर सकते हैं और अपनी आवश्यकताओं के अनुसार इस विधि का उपयोग कर सकते हैं, मुझे आशा है कि यह आपके लिए काम करेगा

public void removeItem(@NonNull Object object) {
        mDataSetList.remove(object);
        notifyDataSetChanged();
    }

5

यहाँ कुछ दृश्य पूरक उदाहरण हैं। किसी श्रेणी को जोड़ने और हटाने के उदाहरणों के लिए मेरा पूरा उत्तर देखें ।

एकल आइटम जोड़ें

सूचकांक में "सुअर" जोड़ें 2

एकल आइटम डालें

String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);

एकल आइटम निकालें

सूची से "सुअर" निकालें।

एकल आइटम निकालें

int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);

4

मैंने उपरोक्त सभी उत्तरों की कोशिश की, लेकिन रिसाइकलव्यू में आइटम डालने या हटाने से डेटासेट में स्थिति के साथ समस्या होती है। delete(getAdapterPosition());ViewHolder के अंदर का उपयोग करके समाप्त हुआ जो वस्तुओं की स्थिति को खोजने में बहुत काम आया।


1
बस एक श्रोता सेट करें और दृश्य धारक के अंदर getAdapterPosition () विधि का उपयोग करें। यह आइटम की स्थिति लौटाएगा।
अरुण

4

मेरे पास जो समस्या थी, मैं उस सूची से एक आइटम निकाल रहा था जो अब एडॉप्टर से जुड़ा नहीं था, यह सुनिश्चित करने के लिए कि आप सही एडॉप्टर को संशोधित कर रहे हैं, आप अपने एडेप्टर में इस तरह की विधि लागू कर सकते हैं:

public void removeItemAtPosition(int position) {
    items.remove(position);
}

और इसे अपने खंड या गतिविधि में इस तरह से कॉल करें:

adapter.removeItemAtPosition(position);

2
  public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<cardview_widgets> list;

public MyAdapter(Context context, List<cardview_widgets> list) {
    this.context = context;
    this.list = list;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(this.context).inflate(R.layout.fragment1_one_item,
            viewGroup, false);
    return new MyViewHolder(view);
}

public static class MyViewHolder extends RecyclerView.ViewHolder {
    TextView txt_value;
    TextView txt_category;
    ImageView img_inorex;
    ImageView img_category;
    TextView txt_date;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        txt_value = itemView.findViewById(R.id.id_values);
        txt_category = itemView.findViewById(R.id.id_category);
        img_inorex = itemView.findViewById(R.id.id_inorex);
        img_category = itemView.findViewById(R.id.id_imgcategory);
        txt_date = itemView.findViewById(R.id.id_date);
    }
}

@NonNull
@Override
public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int i) {

    myViewHolder.txt_value.setText(String.valueOf(list.get(i).getValuee()));
    myViewHolder.txt_category.setText(list.get(i).getCategory());
    myViewHolder.img_inorex.setBackgroundColor(list.get(i).getImg_inorex());
    myViewHolder.img_category.setImageResource(list.get(i).getImg_category());
    myViewHolder.txt_date.setText(list.get(i).getDate());
    myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            list.remove(myViewHolder.getAdapterPosition());
            notifyDataSetChanged();
            return false;
        }
    });
}

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

उम्मीद है इससे आपको मदद होगी।


1

यदि आप आइटम को हटाना चाहते हैं तो आपको ऐसा करना चाहिए: पहले आइटम को हटा दें:

phones.remove(position);

अगले चरण में आपको अपने रिसाइकलर एडॉप्टर को सूचित करना चाहिए जिसे आप इस कोड द्वारा एक आइटम निकालते हैं:

notifyItemRemoved(position);
notifyItemRangeChanged(position, phones.size());

लेकिन अगर आप किसी आइटम को बदलते हैं तो ऐसा करें: पहले अपनी ऑब्जेक्ट के पैरामीटर को इस तरह बदलें:

Service s = services.get(position);
s.done = "Cancel service";
services.set(position,s);

या इसे इस तरह से नया करें:

Service s = new Service();
services.set(position,s);

फिर अपने पुनर्नवीनीकरण अनुकूलक को सूचित करें कि आप इस कोड द्वारा एक आइटम को संशोधित करते हैं:

notifyItemChanged(position);
notifyItemRangeChanged(position, services.size());

आशा है कि आप में मदद करता है।


1
  String str = arrayList.get(position);
  arrayList.remove(str);
  MyAdapter.this.notifyDataSetChanged();

यह वास्तव में एक बुरा विचार है, क्योंकि आप वस्तुओं की एक पूरी तरह से फिर से आकर्षित करने के लिए मजबूर करेंगे, अगर आपके पास बहुत सारे आइटम हैं तो ध्यान देने योग्य अंतराल होगा। कॉल करने के लिए सही बात है notifyItemRemoved(position)
मिनस मीना

फिर आपका सही हम भी सूचित करें। ItRemRemoved (स्थिति) का उपयोग करें अधिसूचितDataSetChanged ()
तरुण उमठ

1

इस विधि को onBindViewHolderलिखने के लिए विधि

holder.remove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Cursor del=dbAdapter.ExecuteQ("delete from TblItem where Id="+values.get(position).getId());
                values.remove(position);
                notifyDataSetChanged();
            }
        });

1

किसी को भी एडॉप्टर वर्ग के बजाय मुख्य वर्ग में कुछ इस तरह से लागू करना चाहता है, आप इसका उपयोग कर सकते हैं:

public void removeAt(int position) {
    peopleListUser.remove(position);

    friendsListRecycler.getAdapter().notifyItemRemoved(position);
    friendsListRecycler.getAdapter().notifyItemRangeChanged(position, peopleListUser.size());
}

जहाँ friendsListRecycler एडाप्टर नाम है


0
 //////// set the position
 holder.cancel.setTag(position);


///// click to remove an item from recycler view and an array list
holder.cancel.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {

            int positionToRemove = (int)view.getTag(); //get the position of the view to delete stored in the tag
            mDataset.remove(positionToRemove);
            notifyDataSetChanged();
                }
            });

0

कस्टम एडेप्टर वर्ग में इंटरफ़ेस करें और पुनर्नवीनीकरण दृश्य पर क्लिक इवेंट को हैंडल करें।

 onItemClickListner onItemClickListner;

public void setOnItemClickListner(CommentsAdapter.onItemClickListner onItemClickListner) {
    this.onItemClickListner = onItemClickListner;
}

public interface onItemClickListner {
    void onClick(Contact contact);//pass your object types.
}
    @Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    // below code handle click event on recycler view item.
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onItemClickListner.onClick(mContectList.get(position));
        }
    });
}

एडेप्टर को परिभाषित करने और कोड के नीचे बुलाया पुनर्नवीनीकरण दृश्य में बाँधने के बाद ।।

        adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
        @Override
        public void onClick(Contact contact) {
            contectList.remove(contectList.get(contectList.indexOf(contact)));
            adapter.notifyDataSetChanged();
        }
    });
}

0

मामले में आप सोच रहे हैं कि मैंने कहां किया कि हम विधि getadcapeposition में एडाप्टर की स्थिति प्राप्त कर सकते हैं (); इसके व्यूअर ऑब्जेक्ट में.इस तरह आपको अपना कोड डालना होगा

mdataset.remove(holder.getadapterposition());

0

गतिविधि में:

mAdapter.updateAt(pos, text, completed);
mAdapter.removeAt(pos);

अपने एडॉप्टर में:

void removeAt(int position) {
    list.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, list.size());
}

void updateAt(int position, String text, Boolean completed) {
    TodoEntity todoEntity = list.get(position);
    todoEntity.setText(text);
    todoEntity.setCompleted(completed);
    notifyItemChanged(position);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.