অ্যান্ড্রয়েড রিসাইক্লারভিউ যোগ করুন এবং আইটেমগুলি অপসারণ


144

আমার কাছে একটি টেক্সটভিউ পাঠ্য বাক্স এবং একটি ক্রস বোতাম ইমেজভিউ সহ একটি পুনর্ব্যবহারযোগ্য ভিউ রয়েছে। আমার রিসাইক্লিউউয়ের বাইরে একটি বোতাম রয়েছে যা ক্রস বোতামটি চিত্র ভিউকে দৃশ্যমান / চলে গেছে।

আমি যখন আইটেম ক্রস বোতামটি চিত্র ভিউ টিপানো হয় তখন আমি পুনর্ব্যবহারযোগ্য থেকে একটি আইটেম সরিয়ে ফেলতে চাই।

আমার অ্যাডাপ্টার:

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>

আমার ক্রসবটন ইমেজভিউয়ের জন্য কীভাবে অনক্লিকের মতো কাজ করতে পারি? একটি ভাল উপায় আছে কি? পুরো আইটেমটি ক্লিক করে আইটেমটি সরানোর জন্য ক্লিক করুন? রিসাইক্লিউরভিউ সম্পাদনা করা প্রয়োজন এমন অবস্থানের একটি তালিকা দেখায়। সর্বোত্তম বাস্তবায়নের বিষয়ে যে কোনও প্রযুক্তিগত পরামর্শ বা মন্তব্য / পরামর্শগুলি প্রশংসিত হবে।


দেখে নিন LINK এ 1 LINK এ 2 এটা ইউ সাহায্য করতে পারে
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
@ চিপ getAdapterPosition () ব্যবহার করুন
টাইলার

2
আপনি দ্রুত উপরে এবং নীচের উভয় থেকে আইটেমগুলি সরিয়ে ফেললে এই কোড কোনও সমস্যার সমাধান করে না।
ভিটো ভালভ

61

প্রথমত, আইটেমটি তালিকা থেকে সরানো উচিত!

  mDataSet.remove(getAdapterPosition());

তারপর:

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

2
আপনার অত্যধিক ধন্যবাদ, মনে করুন যে আমাকে আরও মান যুক্ত করতে হবে মানে এর জন্য আমি কী করতে পারি।
মোহনরাজ এস

`গুলি আপনার অ্যাডাপ্টারের তালিকায় আকার এর সাথে সম্পর্কিত @ হাম্মাদ নাসির।
Zahra.HY

আমিও তাই করেছি, তবে পুনর্ব্যবহারযোগ্যতার উচ্চতা পরিবর্তনশীল নয়। mNotes.remove (অবস্থান); (অবস্থান) notifyItemRemoved; notifyItemRangeChanged (অবস্থান, 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 টি আইটেম রয়েছে এবং আমি সর্বশেষটি সরিয়ে ফেললাম, সেই দৃশ্যে হোল্ডার.ইটিএমভিউ.সেটভিজিবিলিটি (দেখুন.গন), সমস্ত ডেটা লুকান,
হিতেশ ধামশানিয়া

@ হিটেশ ধামশানিয়া এটিকে কেবল লুকিয়ে রাখেনি এবং শেষ দৃশ্যে গেছে
মোস্তফা আন্টার

ভিউ লুকানোর দরকার নেই। ডেটাসেট.রেমোভ (অবস্থান) ঠিকঠাক কাজ করে, তবে আপনার জন্য notifyDatasetChamged () বা notifyItemRemoved (dataset.size () - 1) কল করতে হবে
কারু বেনসন কারু

হোল্ডার.ইটিএমভিউ.সেটভিজিবিলিটি (ভিউ.জোন) জন্য ধন্যবাদ;
কে.হায়োভ

10

সমস্যা

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)

সেরা পন্থা

আপনি যদি আইটেমগুলি সংযোজন / অপসারণের ক্ষেত্রে কী ঘটে তা সঠিকভাবে নির্দিষ্ট না করে (মতামত সম্পর্কে কথা বলছেন), পুনর্ব্যবহারযোগ্য ভিউ বাচ্চাদের কীভাবে তালিকার চারপাশে বিভিন্ন মতামত সরিয়ে নেওয়া যায় সে সম্পর্কে তথ্যের অভাবের কারণে প্রতিক্রিয়াহীনভাবে অ্যানিমেটেড করা হয়।

পরিবর্তে, নীচের কোডটি সুনির্দিষ্টভাবে অ্যানিমেশনটি খেলবে, কেবল যে শিশুটিকে সরানো হচ্ছে (এবং একটি পার্শ্ব নোট হিসাবে, এটি আমার জন্য এটি কোনও IndexOutOfBoundExceptionডেটা স্থির করেছে, স্ট্যাকট্রেস দ্বারা "ডেটা অসঙ্গতি" হিসাবে চিহ্নিত)

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());ভিউহোল্ডারের অভ্যন্তরে ব্যবহার করে শেষ হয়েছে যা আইটেমগুলির অবস্থান সন্ধানে দুর্দান্ত কাজ করেছে।


1
কেবলমাত্র একটি শ্রোতা সেট করুন এবং ভিউ ধারকের ভিতরে getAdapterPosition () পদ্ধতি ব্যবহার করুন use এটি আইটেমের অবস্থান ফিরিয়ে দেবে।
অরুণ

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)
মিনাস মিনা

হ্যাঁ আপনার সঠিক আমরা নোটিফাইডাটাসেট চেঞ্জড ()
তরুন উমথ

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());
}

যেখানে ফ্রেন্ডলিস্টসাইক্র্লারের অ্যাডাপ্টারের নাম


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

আপনি যদি ভাবছেন যে আমি যেমন করেছি তখন আমরা পদ্ধতিটি অ্যাডাপ্টারের অবস্থানটি কোথায় পেতে পারি গ্যাডাডাপ্টারপজিশন (); এটি ভিউহোল্ডার অবজেক্টে রয়েছে so সুতরাং আপনাকে নিজের কোডটি এইভাবে রাখতে হবে

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);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.