Search code examples
androidandroid-recyclerviewadapternotifydatasetchanged

Android change layout presentation in RecyclerView


I want to change layout presentation in RecyclerView from list to grid and vice versa. So I have changed my onCreateViewHolder method to:

if (presentation.equals("grid")) {
    return LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item_grid, parent, false);
}
else {
    return LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item_list, parent, false);   
}

In my feature method, I set different LayoutManager in .setLayoutManager(..) method then notifyDataSetChanged();

if (presentation.equals("grid")) {
    recyclerView.setLayoutManager(new GridLayoutManager(context, 3));
}
else {
    recyclerView.setLayoutManager(new LinearLayoutManager(context));
}
adapter.notifyDataSetChanged();

But when I use this feature, some of the layouts are from grid layout and some from list layout.

I know that RecyclerView reuse elements when they aren't shown, but how to keep show this properly and still reuse elements?


Solution

  • onCreateViewHolder() is only called when RecyclerView doesn't have enough view holders and needs you to create a new one. But it will keep a pool of previously created view holders and reuse them. When you change your presentation to "grid" you start creating new "grid view holders", but the old "list view holders" are still in the pool and are reused. You need a way for your view holders not to mix. I can see a couple of solutions.

    One would be to also change item view type. Normally it is used to be able to display more than one view type at the same time (for example mix small and big items). In your case you still return the same view type for each item, but make it depend on your presentation variable like that:

    @Override
    public int getItemViewType(int position) {
        return presentation.equals("grid") ? 0 : 1;
    }
    

    Another way would be to have two RecyclerViews in your layout. Both could use the same adapter. One would create only grid view holders the other only list view holders. Then you could show and hide them accordingly.