Android RecyclerView: Change layout file LIST to GRID onOptionItemSelected

53,886

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.

Share:
53,886
Pratik Butani
Author by

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, 2020

Comments

  • Pratik Butani
    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 in onCreateViewHolder 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 from List to Grid and Vice Versa in onOptionsItemSelected, here i am calling mAdapter.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:

    enter image description here

    Image of List layout:

    enter image description here

    BUT NOW WHEN I SCROLL and then CHANGING VIEW is Displaying like:

    Grid layout:

    enter image description here

    List layout:

    enter image description here

    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
    Pratik Butani over 8 years
    After 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
    Haresh Chhelana over 8 years
    @PratikButani,Try to use recyclerView.scrollToPosition(position); after set new LayoutManager.
  • crgarridos
    crgarridos almost 8 years
    how 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
    Ramesh sambu over 6 years
    What is isViewWithCatalog how to get that?
  • Pratik Butani
    Pratik Butani over 6 years
    @R2R isViewWithCatalog is boolean variable defined in that activity, which will decide which layout will be come first.
  • Skynet
    Skynet over 5 years
    I'd use a strategy pattern here rather!
  • Sumit Shukla
    Sumit Shukla over 5 years
    @Skynet How you will use a strategy pattern here?
  • Sava Dimitrijević
    Sava Dimitrijević over 5 years
    isViewWithCatalog is also defined in adapter!
  • Pratik Butani
    Pratik Butani over 5 years
    Yeah, That I have passed in argument of constructor. @SavaDimitrijević
  • Sava Dimitrijević
    Sava Dimitrijević over 5 years
    That makes sense. Thank you for the answer!
  • Pratik Butani
    Pratik Butani over 5 years
    Thank you for your upvote : now Q/A both are equal 32:32 :D @SavaDimitrijević
  • Dr Mido
    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
    Dr Mido about 5 years
    I 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
    Mohammad Yahia about 5 years
  • bluestart83
    bluestart83 over 2 years
    This definitively solve my same issue