Ich erstelle eine Liste von Karten, die mit RecyclerView angezeigt werden sollen. Jede Karte verfügt über eine Schaltfläche zum Entfernen dieser Karte aus der Liste.
Wenn ich notifyItemRemoved () verwende , um die Karte in der RecyclerView zu entfernen, wird das Element entfernt und animiert, aber die Daten in der Liste werden nicht korrekt aktualisiert.
Wenn ich stattdessen zu notifyDataSetChanged () wechsle, werden die Elemente in der Liste entfernt und korrekt aktualisiert, aber dann werden die Karten nicht animiert.
Hat jemand Erfahrung mit der Verwendung von notifyItemRemoved () und weiß, warum es sich anders verhält als notifyDataSetChanged?
Hier ist ein Stück Code, den ich benutze:
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if(position >0){
RiskViewHolder riskHolder = (RiskViewHolder)holder;
final int index = position - 1;
final DetectedIssue anIssue = issues.get(index);
riskHolder.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int index = issues.indexOf(anIssue);
issues.remove(anIssue);
notifyItemRemoved(index);
//notifyDataSetChanged();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
@Override
public int getItemCount() {
return (issues.size()+1);
}
Antworten:
Verwenden Sie notifyItemRangeChanged (position, getItemCount ()); nach notifyItemRemoved (Position);
Sie müssen keinen Index verwenden, sondern nur die Position. Siehe Code unten.
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>(); @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element if(position >0){ RiskViewHolder riskHolder = (RiskViewHolder)holder; riskHolder.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { issues.remove(position); notifyItemRemoved(position); //this line below gives you the animation and also updates the //list items after the deleted item notifyItemRangeChanged(position, getItemCount()); } catch (SQLException e) { e.printStackTrace(); } } }); } } @Override public int getItemCount() { return issues.size(); }
quelle
notifyItemRemoved(position);
funktioniert aber gut alleine (mit Animation). WasnotifyItemRangeChanged(position, getItemCount());
macht das Ich kann den Unterschied nicht sehen. Vielen DankVersucht
public void removeItem(int position) { this.taskLists.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, getItemCount() - position); }
und wie ein Zauber arbeiten.
quelle
getItemCount() - position
statt nur verwendengetItemCount()
?Mein Fehler, notifyItemChanged (Position) ist hilflos, das Positionselement kann entfernt werden und das Positionselement + 1 ist in Ordnung, aber die Elemente beginnen bei Position + 2. Sie erhalten eine Ausnahme. Bitte verwenden Sie notifyItemRangeChanged (Position, getItemCount ()); nach notifyItemRemoved (Position);
so was:
public void removeData(int position) { yourdatalist.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position,getItemCount()); }
quelle
Wie @pskink vorgeschlagen hat, sollte es in meinem Fall mit (Index + 1) sein
notifyItemRemoved(index+1)
, wahrscheinlich weil ich den obersten Index reserviere, dhposition=0
für einen Header.quelle
Sie können
getLayoutPosition()
aus dem verwendenRecyclerView.ViewHolder
getLayoutPosition()
gibt die genaue Position des Elements im Layout an und Code istholder.removeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Position for remove int modPosition= holder.getLayoutPosition(); //remove item from dataset numbers.remove(modPosition); //remove item from recycler view notifyItemRemoved(modPosition); } });
quelle
**my solution looks like this** this way is unnecessary to use the heavy method: //notifyItemRangeChanged(xx,xx) /** * * recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position * * @param recyclerView * @param view:can be the deep one inside the item,or the item itself . * @return */ public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) { if (view.getId() == parentId) return recyclerView.getChildAdapterPosition(view); View viewGroup = (View) view.getParent(); if (viewGroup != null && viewGroup.getId() == parentId) { return recyclerView.getChildAdapterPosition(viewGroup); } //recursion return getParentAdapterPosition(recyclerView, viewGroup, parentId); } //wherever you set the clickListener . holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener); holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener); @Override public boolean onLongClick(View v) { final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item); return true; }
quelle
In meinem Fall verwende ich den Inhaltsanbieter und einen benutzerdefinierten RecyclerView-Adapter mit Cursor. In dieser Codezeile benachrichtigen Sie:
getContext().getContentResolver().notifyChange(uri, null);
Angenommen, in Ihrem recyclerView-Adapter (Schaltfläche Löschen):
Uri currentUri = ContentUris.withAppendedId(DatabaseContract.ToDoEntry.CONTENT_URI_TODO, id); int rowsDeleted = mContext.getContentResolver().delete(currentUri, null, null); if (rowsDeleted == 0) { Log.d(TAG, "onClick: Delete failed"); } else { Log.d(TAG, "onClick: Delete Successful"); }
Und in Ihrem Datenbankanbieter:
case TODO_ID: selection = DatabaseContract.ToDoEntry._ID + "=?"; selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))}; rowsDeleted = database.delete(DatabaseContract.ToDoEntry.TODO_TABLE_NAME, selection, selectionArgs); if (rowsDeleted != 0){ getContext().getContentResolver().notifyChange(uri, null); } return rowsDeleted;
quelle
Sie sollten den Listener remove in der ViewHolder-Klasse hinzufügen
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCancel(getAdapterPosition()); } }); private void onCancel(int position) { if (position >= issues.size()) return; issues.remove(position); notifyItemRemoved(position); }
quelle