it-swarm.com.de

Android RecyclerView Hinzufügen und Entfernen von Elementen

Ich habe eine RecyclerView mit einem TextView-Textfeld und einer Kreuztaste ImageView. Ich habe eine Schaltfläche außerhalb der Recyclingübersicht, mit der die Schaltfläche "ImageView" sichtbar/verschwunden ist.

Ich möchte ein Element aus der Neuübersicht entfernen, wenn dieses Element die Schaltfläche ImageView kreuzt.

Mein Adapter:

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

Mein Layout ist:

<?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>

Wie kann ich für mein crossButton ImageView so etwas wie ein onClick zum Laufen bringen? Gibt es einen besseren Weg? Vielleicht den ganzen Artikel durch einen Klick in "Artikel entfernen" ändern? Die Recyclingübersicht zeigt eine Liste der Orte, die bearbeitet werden müssen. Alle technischen Ratschläge oder Kommentare/Vorschläge zur besten Implementierung würden sehr geschätzt.

122

Ich habe etwas Ähnliches gemacht. In Ihrem 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());
}

Hoffe das hilft.

Edit:

getPosition() ist jetzt veraltet, verwenden Sie stattdessen getAdapterPosition().

224
paradite

zuallererst sollte der Gegenstand von der Liste entfernt werden!

  mDataSet.remove(getAdapterPosition());

dann:

  notifyItemRemoved(getAdapterPosition());
  notifyItemRangeChanged(getAdapterPosition(),mDataSet.size());
46
Zahra.HY

wenn der Gegenstand immer noch nicht entfernt wurde, benutze diese magische Methode :)

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

Möglicherweise eine doppelte Antwort, aber sehr nützlich für mich. Sie können die unten angegebene Methode in RecyclerView.Adapter<RecyclerView.ViewHolder> Implementieren und diese Methode gemäß Ihren Anforderungen verwenden. Ich hoffe, dass sie für Sie funktioniert

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

Tatsächlich werden alle RecyclerView-Childs mit dem zuvor erwähnten Code (den Sie hier unten finden) animiert, wenn ein einzelnes Element entfernt wird, und es ist überhaupt keine reaktionsfähige Lösung, auch weil es einige potenzielle versteckte Probleme aufweist

public void remove(int position) {
    dataset.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, mDataSet.size());
}

Stattdessen spielt das folgende Snippet die Animation nur auf dem Kind ab, das entfernt wird, und meinerseits hat es aufgehört, IndexOutOfBoundExceptions zu werfen, was vom Debugger als "Dateninkonsistenz" markiert wurde.

void remove(int position) {
    dataset.removeAt(position);
    notifyItemChanged(position);
    notifyItemRangeRemoved(position, 1);
}

Wenn wir in die Klasse RecyclerView eintauchen, können wir ein Stück Javadoc finden, das die Erklärung enthält. In der Tat müssen wir als zweiten Parameter die Anzahl der Elemente übergeben, die aus dem Datensatz entfernt werden, nicht die Gesamtzahl der Elemente

    /**
     * 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);
    }
6

Ich habe alle oben genannten Antworten ausprobiert, aber das Einfügen oder Entfernen von Elementen in recyclerview führt zu Problemen mit der Position im DataSet. Am Ende wurde delete(getAdapterPosition()); im viewHolder verwendet, was beim Auffinden der Position von Elementen sehr hilfreich war.

4
Arun

Das Problem, das ich hatte, war, dass ich ein Element aus der Liste entfernte, das nicht mehr mit dem Adapter verknüpft war, um sicherzustellen, dass Sie den richtigen Adapter ändern. Sie können eine Methode wie die folgende in Ihrem Adapter implementieren:

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

Und nennen Sie es in Ihrem Fragment oder Ihrer Aktivität so:

adapter.removeItemAtPosition(position);
3
Horatio

Hier einige visuelle Ergänzungsbeispiele. Siehe meine ausführlichere Antwort für Beispiele zum Hinzufügen und Entfernen eines Bereichs.

Einzelnen Artikel hinzufügen

Fügen Sie "Pig" am Index 2 Hinzu.

Insert single item

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

Einzelnen Gegenstand entfernen

Entfernen Sie "Pig" aus der Liste.

Remove single item

int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
3
Suragch
  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();
}}      

ich hoffe das hilft dir.

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

Wenn jemand so etwas in der Main-Klasse anstelle der Adapter-Klasse implementieren möchte, kann Folgendes verwendet werden: `public void removeAt (int position) {peopleListUser.remove (position);

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

dabei ist friendsListRecycler der Name des Adapters

1
Forest baba

wenn Sie Artikel entfernen möchten, sollten Sie dies tun: Zuerst Artikel entfernen:

phones.remove(position);

im nächsten Schritt sollten Sie Ihren Recycler-Adapter darüber informieren, dass Sie einen Artikel mit folgendem Code entfernen:

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

wenn Sie jedoch ein Objekt ändern, gehen Sie folgendermaßen vor: Ändern Sie zunächst einen Parameter Ihres Objekts wie folgt:

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

oder neu so:

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

benachrichtigen Sie dann Ihren Recycler-Adapter, dass Sie einen Artikel mit diesem Code ändern:

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

hoffnung hilft dir.

Zu Methode onBindViewHolder Schreiben Sie diesen Code

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

schnittstelle in benutzerdefinierte Adapterklasse umwandeln und Klickereignis in der Recycler-Ansicht verarbeiten.

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

nach dem Definieren des Adapters und Einbinden in die Recycler-Ansicht mit dem folgenden Code.

        adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
        @Override
        public void onClick(Contact contact) {
            contectList.remove(contectList.get(contectList.indexOf(contact)));
            adapter.notifyDataSetChanged();
        }
    });
}
0
Android Team
 //////// 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
roshan posakya