I have a RecyclerView
that can show items as list, small grids or large grid and this can be change at runtime. Depending on what style user chooses i inflate different layout in onCreateViewHolder
.
I also use layoutManger.setSpanSizeLookUp()
to switch between styles. My code looks like this
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);
}
The problem is to force onCreateViewHolder
to be called I'm creating a new object every time user changes the style. Is there any other way?! to force onBindViewHolder()
to be recalled. I simply use adapter.notifyDataSetChanged()
How can i get something similar for onCreateViewHolder?
Any solution that doesn't uses multiple adapters is good enough!
By default it have 5. you can increase as per your need. Save this answer.
This method internally calls onBindViewHolder to update the ViewHolder contents with the item at the given position and also sets up some private fields to be used by RecyclerView. This method calls onCreateViewHolder to create a new ViewHolder and initializes some private fields to be used by RecyclerView.
A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results. While LayoutParams belong to the LayoutManager , ViewHolders belong to the adapter.
From the docs notifyDataSetChanged() : Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
What you need to do is:
Adapter
:Views
that your Adapter
can inflate:private static final int LARGE_GRID_ITEM = -1;
private static final int SMALL_GRID_ITEM = -2;
Create a field that can store current type mCurrentType
Use your Adapter's
getItemViewType
. For example like this:
@Override
public int getItemViewType (int position) {
return mCurrentType;
}
createViewHolder
use the viewType
to decide what type of ViewHolder
you need to create.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();
}
Its not the optimal choice but it's better to create a new Adapter
, which will call onCreateViewHolder()
. This way you can avoid your troubles, by the cost of very tiny performance issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With