I am creating a list of cards to display using the RecyclerView, where each card has a button to remove that card from the list.
When i use notifyItemRemoved
**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;
}
You should add remove listener in ViewHolder class
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);
}
my mistake , notifyItemChanged(position) is helpless,the item of position can be removed ,and the item of position+1 is fine,but the items start from position+2,you will get an Exception, please use notifyItemRangeChanged(position,getItemCount()); after notifyItemRemoved(position);
like this:
public void removeData(int position) {
yourdatalist.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,getItemCount());
}
As @pskink suggested it was supposed to be (index+1) in my case with notifyItemRemoved(index+1)
, probably because i am reserving the top index i.e. position=0
for a header.
In my case I use Content Provider and a Custom RecyclerView Adapter with Cursor. This line of code is where you notify:
getContext().getContentResolver().notifyChange(uri, null);
Assuming In your recyclerView adapter (Delete Button):
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");
}
And in your Database Provider:
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;
Use notifyItemRangeChanged(position, getItemCount()); after notifyItemRemoved(position);
You don't need to use index, just use position. See code below.
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();
}