其他分享
首页 > 其他分享> > android-为什么RecyclerView项目在GridLayoutManager中随机移动位置?

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