android-为什么RecyclerView项目在GridLayoutManager中随机移动位置?
作者:互联网
我正在使用gridLayoutManager显示我的RecyclerView项目.我还对项目实施了onClick和onLongClick
public void onItemClicked(int position) {
final SquareImageView clickedItem = (SquareImageView)(lLayout.findViewByPosition(position));
if (actionMode != null) {
if(clickedItem.getPaddingLeft() == 1) clickedItem.setPadding(7,7,7,7);
else clickedItem.setPadding(1,1,1,1);
} else {
thumbView = (SquareImageView)(lLayout.findViewByPosition(position));
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH)
zoomImageFromThumb(position);
else
imageFromThumb(position);
}
}
@Override
public boolean onItemLongClicked(int position) {
final SquareImageView clickedItem = (SquareImageView)(lLayout.findViewByPosition(position));
clickedItem.setPadding(7,7,7,7);
if (actionMode == null) {
actionMode = startSupportActionMode(new ActionModeCallback());
actionMode.getMenu().findItem(R.id.menu_remove).setIcon(new IconDrawable(this, Iconify.IconValue.fa_trash).colorRes(R.color.accent_color).actionBarSize());
}
return true;
}
如您所见,如果actionMode不为null,则只需在longClick和click上更改被单击项的填充.
一切都按预期工作:如果我长时间单击第一项,则其填充会改变,但是当我滚动到网格的底部时,填充会移动到底部图像或其他随机图像.再次,如果我滚动到顶部,则顶部项目将没有填充,并且填充已移至其他随机元素.
这是由于元素回收造成的问题吗?我该如何摆脱呢?
解决方法:
是.此问题归因于视图的回收,并且是预期的行为.
这很容易理解.滚动回收器视图时,只有有限的视图集会保留在内存中.但是正如您所看到的,在单击之后,填充仅被应用一次.那么,视图被回收后会发生什么呢?系统将如何记住再次添加填充?
因此,系统通过调用RecyclerViewAdapter的onBindViewHolder()来重新绘制视图项目,该视图持有者可能是其他回收项目的视图持有者.您需要确保每次调用onBindViewHolder()时都要做两件事-
1)如果选择了该项,则设置填充(这可确保您选择的项始终得到填充),并且
2)如果未选中项目,则将padding设置为0(这确保了随机项目不会得到padding.再次,这是可以预期的,因为选中的项目的ViewHolder可能会重新用于未选中的项目!)
您可以使用SparseBooleanArray来存储所选位置,并在onBindViewHolder中检查其值.请记住,您还需要在单击后的位置调用notifyItemChanged(i),以便重新绘制该项目(再次调用onBindViewHolder()).
大致来说,您可以在适配器的代码中添加两件事:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
//...
private SparseBooleanArray selectedItems = new SparseBooleanArray();
// Call this from your onItemLongClicked()
public void selectItem(int position){
selectedItems.put(position, true);
notifyItemChanged(position);
}
// Call this in your onItemClicked() to check if position is selected
public boolean isItemSelected(int position){
return selectedItems.get(position, false);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// your existing code
if(selectedItems.get(position, false)){
holder.itemView.setPadding(7,7,7,7);
}
else {
holder.itemView.setPadding(1,1,1,1);
}
}
}
标签:android-recyclerview,gridlayoutmanager,android 来源: https://codeday.me/bug/20191120/2040442.html