我正在使用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;
}
如您所见,我只需在longclick和click(如果actionmode不为空)更改单击项的填充。
一切都按预期工作:如果我长时间单击第一个项目,它的填充确实会改变,但当我滚动到网格底部时,填充已移动到底部图像或其他一些随机图像。再次,如果我滚动到顶部,顶部项将没有填充,并且填充已移动到其他随机元素。
这个问题是由于元素的回收吗?我该怎么处理?
最佳答案
对。这个问题是由于视图的循环使用造成的,是预期的行为。
这很容易理解。滚动回收器视图时,内存中只保留有限的视图集。但正如您所看到的,填充只应用一次,就在单击之后。那么,风景被回收后会发生什么呢?系统将如何记住再次添加填充?
因此,系统通过调用recyclerviewapter的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);
}
}
}