40

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
  • 60,504
  • 58
  • 273
  • 437
  • 1
    This answer might help: http://stackoverflow.com/a/24933117/2649012 – Phantômaxx Feb 18 '15 at 11:03
  • use this RecyclerView.setHasFixedSize(true); – Amrut Bidri Feb 26 '15 at 06:52
  • its `mRecyclerView.setHasFixedSize(true);` but not working for me. any other solution? – Pratik Butani Feb 26 '15 at 07:03
  • I think this respost can help you: [RecyclerView: how to clear cached/recycled views?](http://stackoverflow.com/a/27961601/4098739) – Luciano Mar 14 '15 at 20:27
  • have you solved this yet? – Bojan Kseneman Apr 25 '15 at 19:32
  • I have posted my solution as answer @Harsha – Pratik Butani Sep 24 '15 at 05:25
  • i need some more explanation please why because am new to android studio.how to add those list or grid icons optionsmenu icons how to visible and invisible option icons and this entire thing in android navigationdrawer with home fragment view.that options items icon in rightside middle of the screen.how to change toolbar for individual fragment also is it possible along with drawer – Harsha Sep 24 '15 at 05:33
  • Ohh. So i have to explain everything and that is not possible on #SO @Harsha – Pratik Butani Sep 24 '15 at 05:38
  • oh not a problem can you provide any reference links for better understanding.i dont want to disturb.am plan to design like android telugu matrimoney app like for those optionitem icons.Thank you – Harsha Sep 24 '15 at 05:44
  • how to place those list and grid items and how to change the icons from menu.xml with visible gone properties or any otehr please help me – Harsha Jan 30 '16 at 09:01
  • http://developer.android.com/intl/es/guide/topics/ui/menus.html @Harsha – Pratik Butani Jan 30 '16 at 09:42
  • hi pratik please can you post that options menu methode and list and grid changing sample snippet please help me. – Harsha Feb 01 '16 at 05:56
  • hi am able to change the list and grid view data when user clicked on options menu icon but how to replace list with grid and list icons – Harsha Feb 01 '16 at 12:25
  • http://stackoverflow.com/a/20614728/1318946 @Harsha – Pratik Butani Feb 01 '16 at 12:27
  • thanks all providing sample links and give some valuable information.finally achieved it.options menu icon changing and list grid views.but how to replace grid with costume layout. – Harsha Feb 16 '16 at 09:14
  • setLayoutManager(isProductViewAsList ? new LinearLayoutManager(this) : new GridLayoutManager(this, 2)); here we need to set cusome grid row layout – Harsha Feb 16 '16 at 09:14
  • @PratikButani Can you please tell me isProductViewAsList about this variable and where will i declared? or can you plz send me full code. – Google Jun 16 '16 at 12:15

4 Answers4

41

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.

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
12

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);
}
Mohammad Yahia
  • 483
  • 9
  • 19
  • 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 – Dr Mido Mar 17 '19 at 09:17
  • 3
    see this https://android.googlesource.com/platform/development/+/77b5d39/samples/browseable/RecyclerView/src/com.example.android.recyclerview/RecyclerViewFragment.java – Mohammad Yahia Mar 17 '19 at 14:45
10

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);
Alessandro Roaro
  • 4,665
  • 6
  • 29
  • 48
2

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
  • 60,504
  • 58
  • 273
  • 437