我有一个RecyclerView,可以将项目显示为列表,小网格或大网格,并且可以在运行时进行更改。根据用户选择的样式,我在onCreateViewHolder中填充不同的布局。

我还使用layoutManger.setSpanSizeLookUp()在样式之间进行切换。我的代码看起来像这样

layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
                return 1;
            else
                return columnCount; //show one item per row
        }
    });

@Override
public void onClick(View v) {
    if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
        showType = ProductAdapter.SHOW_TYPE_LARGE_GRID;
    else
        showType = ProductAdapter.SHOW_TYPE_SMALL_GRID;


    int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
    adapter = new ProductAdapter(getActivity(), productList, showType);
    recyclerView.setAdapter(adapter);
    layoutManager.scrollToPosition(firstVisibleItem);
}

问题是,每次用户更改样式时,都会强制调用onCreateViewHolder。我正在创建一个新对象。还有其他办法吗?强制召回onBindViewHolder()。我只是使用adapter.notifyDataSetChanged()我如何获得类似的onCreateViewHolder?
任何不使用多个适配器的解决方案就足够了!

最佳答案

您需要做的是:

  • 修改您的Adapter:


  • 指定您的Views可以充气的两种类型的Adapter:

  • private static final int LARGE_GRID_ITEM = -1;
    private static final int SMALL_GRID_ITEM = -2;
    
  • 创建一个可以存储当前类型的字段mCurrentType
  • 使用您的Adapter's getItemViewType 。例如这样的:

  • @Override
    public int getItemViewType (int position) {
        return mCurrentType;
    }
    
  • createViewHolder中,使用viewType决定需要创建哪种类型的ViewHolder

  • public final RecyclerView.ViewHolder createViewHolder (ViewGroup parent, int viewType){
        if (viewType == LARGE_GRID_ITEM) {
            //return large grid view holder
        } else {
            //return small grid view holder
        }
    }
    
  • 另外,您可以创建方法:

  • public void toggleItemViewType () {
        if (mCurrentType == LARGE_GRID_ITEM){
            mCurrentType = SMALL_GRID_ITEM;
        } else {
            mCurrentType = LARGE_GRID_ITEM;
        }
    }
    
    public boolean displaysLargeGrid(){
        return mCurrentType == LARGE_GRID_ITEM;
    }
    
  • 修改您发布的代码:

  • layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (adapter.displaysLargeGrid()) {
                    return 1;
                } else {
                    return columnCount; //show one item per row
                }
            }
        });
    
    @Override
    public void onClick(View v) {
        adapter.toggleItemViewType();
        adapter.notifyDataSetChanged();
    }
    

    10-06 03:43