Android RecyclerView: Change layout file LIST to GRID onOptionItemSelected
Solution 1
I found solution with the starting of activity I have set LinearLayoutManager
like:
mLayoutManager = new LinearLayoutManager(this);
mProductListRecyclerView.setLayoutManager(mLayoutManager);
after that onOptionsItemSelected
written like:
case R.id.menu_product_change_view:
isViewWithCatalog = !isViewWithCatalog;
supportInvalidateOptionsMenu();
//loading = false;
mProductListRecyclerView.setLayoutManager(isViewWithCatalog ? new LinearLayoutManager(this) : new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
mProductListRecyclerView.setAdapter(mAdapter);
break;
and changing view in onCreateViewHolder
like:
@Override
public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(isViewWithCatalog ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null);
ProductRowHolder mh = new ProductRowHolder(v);
return mh;
}
From Starting to Ending you have to manage isViewWithCatalog variable for displaying which layout first.
Solution 2
In this SDK samples there is a complete example however it uses one layout file for both LayoutManagers
For keeping the scrolling position when switching the layout they used this function
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
// If a layout manager has already been set, get current scroll position.
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
}
switch (layoutManagerType) {
case GRID_LAYOUT_MANAGER:
mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
break;
case LINEAR_LAYOUT_MANAGER:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
break;
default:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
}
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
}
Solution 3
I solved this problem by setting the adapter again to the RecyclerView
, after changing the layout manager.
listView.setLayoutManager(new LinearLayoutManager(this));
listView.setAdapter(adapter);
Solution 4
I think after scrolling and changed back to grid view, the first item is not recreated. I solved this by override getItemViewType()
and inflate the layout files in onCreateViewHolder
accordingly.
Pratik Butani
Pratik Butani is Android/Flutter Lead at 7Span - Ahmedabad. He is working with Flutter Development since 2020 and Android Development since 2013. He is on the list of Top 100 User’s (85th) in India and Top 10 User’s (6th) in Gujarat as Highest Reputation Holder on StackOverflow. He was co-organizer at Google Developer Group – Rajkot in 2014-17. All-time Learner of new things, Googler and Eager to Help IT Peoples. He is also likes to share his knowledge of Android and Flutter with New Learner. SOReadyToHelp ツ Fell in Love with Android ツ I really feel proud to up-vote My Favorite #SO friend. => Android Application Developer by Passion :) => Being Helpful by Nature ;) => Now in List of Top 100 User's (85) in India and Top 10 User's (6) in Gujarat as Highest Reputation Holder on StackOverflow => Visit my blogs for learning new things : Happy to Help :) :) => My Apps on Playstore: AndroidButs & PratikButani => My Articles on Medium => Join Me on LinkedIn => Tweet Me on Twitter => Follow Me on Quora - Top Writer on Quora in 2017 => Hangout with Me on [email protected] => Social Networking Facebook => Get Users list whose bio's contains given keywords More about me :) -> Pratik Butani
Updated on March 12, 2020Comments
-
Pratik Butani about 4 years
I am developing an Android Application for Online Shopping. I have created following view for List of Products using
RecyclerView
, in that i want to change view on selecting option menu item:I have created following adapter named
ProductAdapter
, in that I have implemented code for changing layout inonCreateViewHolder
for selecting layout file based on boolean value.Code of Adapter
ProductAdapter
:/*** * ADAPTER for Product to binding rows in List */ private class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductRowHolder> { private List<Product> productList; private Context mContext; public ProductAdapter(Context context, List<Product> feedItemList) { this.productList = feedItemList; this.mContext = context; } @Override public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(isProductViewAsList ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null); ProductRowHolder mh = new ProductRowHolder(v); return mh; } @Override public void onBindViewHolder(ProductRowHolder productRowHolder, int i) { Product prodItem = productList.get(i); // Picasso.with(mContext).load(feedItem.getName()) // .error(R.drawable.ic_launcher) // .placeholder(R.drawable.ic_launcher) // .into(productRowHolder.thumbnail); double price = prodItem.getPrice(); double discount = prodItem.getDiscount(); double discountedPrice = price - (price * discount / 100); String code = ""; if(prodItem.getCode() != null) code = "[" + prodItem.getCode() + "] "; productRowHolder.prodIsNewView.setVisibility(prodItem.getIsNew() == 1 ? View.VISIBLE : View.INVISIBLE); productRowHolder.prodNameView.setText(code + prodItem.getName()); productRowHolder.prodOriginalRateView.setText("Rs." + new BigDecimal(price).setScale(2,RoundingMode.DOWN)); productRowHolder.prodDiscView.setText("" + new BigDecimal(discount).setScale(2,RoundingMode.DOWN) + "% off"); productRowHolder.prodDiscRateView.setText("Rs." + new BigDecimal(discountedPrice).setScale(2,RoundingMode.DOWN)); productRowHolder.prodOriginalRateView.setPaintFlags(productRowHolder.prodOriginalRateView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); } @Override public int getItemCount() { return (null != productList ? productList.size() : 0); } public class ProductRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener { //Declaration of Views public ProductRowHolder(View view) { super(view); view.setOnClickListener(this); //Find Views } @Override public void onClick(View view) { //Onclick of row } } }
After that i have done code for Changing
RecyclerView
layout fromList
toGrid
and Vice Versa inonOptionsItemSelected
, here i am callingmAdapter.notifyDataSetChanged();
so it will call adapter again and change value.onOptionsItemSelected:
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement switch (id) { case R.id.action_settings: return true; case android.R.id.home: finish(); break; case R.id.product_show_as_view: isProductViewAsList = !isProductViewAsList; supportInvalidateOptionsMenu(); mRecyclerView.setLayoutManager(isProductViewAsList ? new LinearLayoutManager(this) : new GridLayoutManager(this, 2)); mAdapter.notifyDataSetChanged(); break; } return super.onOptionsItemSelected(item); }
I got little bit success like:
Image of
Grid
layout:Image of
List
layout:BUT NOW WHEN I SCROLL and then CHANGING VIEW is Displaying like:
Grid
layout:List
layout:I dont know why it happens after scrolling. Is there any other way to change view like this.
Today i just saw that this problem is because of
ImageView
, without it working perfectly.Help please, You help will be appreciated.
-
Pratik Butani over 8 yearsAfter scrolling to 30-40 items and then if i try to change view and it will be start again with 1 position to scroll. Is there any solution for this?
-
Haresh Chhelana over 8 years@PratikButani,Try to use recyclerView.scrollToPosition(position); after set new LayoutManager.
-
crgarridos almost 8 yearshow I can recover the adapter position? I'm thinking about to create a method who save the last position got it by onBindViewHolder but still thinking there is a better way
-
Ramesh sambu over 6 yearsWhat is
isViewWithCatalog
how to get that? -
Pratik Butani over 6 years@R2R
isViewWithCatalog
is boolean variable defined in that activity, which will decide which layout will be come first. -
Skynet over 5 yearsI'd use a strategy pattern here rather!
-
Sumit Shukla over 5 years@Skynet How you will use a strategy pattern here?
-
Sava Dimitrijević over 5 years
isViewWithCatalog
is also defined in adapter! -
Pratik Butani over 5 yearsYeah, That I have passed in argument of constructor. @SavaDimitrijević
-
Sava Dimitrijević over 5 yearsThat makes sense. Thank you for the answer!
-
Pratik Butani over 5 yearsThank you for your upvote : now Q/A both are equal 32:32 :D @SavaDimitrijević
-
Dr Mido about 5 years@pratik-butani can you please update your answer with full adapter constructor ? and how you pass this
isViewWithCatalog
variable in MainActivity ? -
Dr Mido about 5 yearsI know there's a long time since this answer, I see the current example page is not found, please If there's a complete example like it inform me
-
Mohammad Yahia about 5 years
-
bluestart83 over 2 yearsThis definitively solve my same issue