3

I am basically trying the achieve this design principle (from Google's Material Design): enter image description here Thus I've made a parent RecyclerView with a LinearLayoutManager, then in the RecyclerView adapter, I've put the child RecyclerView with a GridLayoutManager for the "rich media" section (Action area 2). Everything works fine, except for the fact that I've set the internal RecyclerView grid to have a match_parent width and a wrap_content height, but it won't calculate the size of the content properly, seemingly leaving it at 0 & thus hidden. If I set the child RecyclerView to a specific height, the items show within, but are then of course cut off at the bottom. Others seem to have come across this problem, but in their case, both have linear layouts. (Also see "Khay's" answer here.)

Now my question is, how would one override the onMeasure method as "pptang" did in the accepted answer of the linked question above, but within a custom GridLayoutManager instead of a custom LinearLayoutManager? I haven't posted my code here, because it's essentially the identical to the one linked, only that I need to make a custom GridLayoutManager instead for the child RecyclerView, so that it measures correctly as "pptang's" answer states.

Otherwise, is there a better way than to use 1 RecyclerView inside a 2nd RecyclerView? Can only 1 RecyclerView populate an activity/fragment both with a list of the above CardViews and a grid of unique items within each CardView?

Community
  • 1
  • 1
inferKNOX
  • 109
  • 1
  • 3
  • 12
  • According to material design guidelines "Limit supplemental actions to two actions". How many items do you want to add in the parent list? How is the scrolling going to work? Both grid and list use vertical scrolling? – masp Sep 08 '16 at 15:31
  • I want to have several `ViewPager` tabs; one with 3 parent `CardViews`, another with maybe 8 parent `CardViews` and another with about 5 parent `CardViews`. The intent is for the grid to be completely "open", thus, no internal scrolling, and only for the parent `CardViews` to scroll vertically. According to what I've seen, having one `RecyclerView` inside another also interferes with the toolbar hiding (`CoodinatorLayout`), where if you try to scroll by holding the `RecyclerView` grid, the toolbar doesn't hide, but only hides when holding somewhere outside the child `RecyclerViews` – inferKNOX Sep 08 '16 at 17:04
  • I think I may have gone off at a tangent to what you actually asked @masp. Sorry. Within the individual `CardViews`, I just want to have the title and icon at the top, grid in the centre, and an "expander" to hide some supporting text. Possibly to also give the `Cardview's` header section the ability to hide/collapse and show/expand the grid, like an `ExpandableListView`. – inferKNOX Sep 08 '16 at 17:16
  • You say "The intent is for the grid to be completely "open", thus, no internal scrolling, and only for the parent CardViews to scroll vertically." This means you don't need recycler view inside recycler view. One Gridlayout manager is enough. I haven't tried what @Gustavo is suggesting, so I don't know if it will cover everything you ask but it is in the right direction. – masp Sep 08 '16 at 17:36
  • I'm not following your train of thought, @masp . I've used a similar method to what @Gustavo suggested (see the link in my comment by that answer), but it gives a pretty different result from that Google illustration. I don't want to use a `RecyclerView` inside another one, but I can't see any other way to achieve the above effect. I'm not mentioning `ListView`/`GridView`/etc because `RecyclerView` replaces them, so which other way? How do you make 1 `RecyclerView` make a list of `CardViews` and also dynamically populate a grid in each of those `CardViews`? – inferKNOX Sep 08 '16 at 18:00
  • I am sure you shouldn't use recyclerView in a recyclerView. Don't chase that. Check this http://blog.sqisland.com/2014/12/recyclerview-grid-with-header.html for the getSpanSize() method. And also you can check all the mergeAdapters libraries. Like this https://github.com/martijnvdwoude/recycler-view-merge-adapter but I haven't check if you can put a grid in there and again not a big fan of that either. Also very good is this http://stackoverflow.com/a/28533234/6774854 – masp Sep 08 '16 at 19:04
  • I actually learnt how to make `RecyclerViews` with headers from exactly that tutorial. If you look below by my comment to @Gustavo's answer, I posted the exact same link. I've even kept the [autofit grid method from the follow up tutorial](http://blog.sqisland.com/2014/12/recyclerview-autofit-grid.html) for my inner `RecyclerView` in this above case. I've had the app like that up to this point, but haven't been to happy with the design, so what I want to know is how exactly Google would have us achieve the design they have recommended, because that is actually the ideal design for me. – inferKNOX Sep 08 '16 at 20:21
  • The Best Way - to use any library, for example [RendererRecyclerViewAdapter](https://github.com/vivchar/RendererRecyclerViewAdapter), see CompositeViewRenderer. Also please loot at this answer https://stackoverflow.com/a/48464993/4894238 – Vitaly Jan 26 '18 at 16:24

2 Answers2

3

You can build it with only one RecyclerView using the library SectionedRecyclerViewAdapter.

You can find the full code for the example of the image below here.

enter image description here

First create a Section class:

class MySection extends StatelessSection {

    String title;
    String subtitle;
    List<String> list;

    public MySection(String title, String subtitle, List<String> list) {
        // call constructor with layout resources for this Section header, footer and items 
        super(R.layout.section_header, R.layout.section_item);

        this.title = title;
        this.subtitle = subtitle;
        this.list = list;
    }

    @Override
    public int getContentItemsTotal() {
        return list.size(); // number of items of this section
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        // return a custom instance of ViewHolder for the items of this section
        return new MyItemViewHolder(view);
    }

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        MyItemViewHolder itemHolder = (MyItemViewHolder) holder;

        // bind your view here
        itemHolder.tvItem.setText(list.get(position));
    }

    @Override
    public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
        return new SimpleHeaderViewHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
        MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;

        // bind your header view here
        headerHolder.tvTitle.setText(title);
        headerHolder.tvSubTitle.setText(subtitle);
    }
}

Then you set up the RecyclerView with your Sections:

// Create an instance of SectionedRecyclerViewAdapter 
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();

// Create your sections with the list of data for each year
MySection section1 = new MySection("Title", "Subhead", firstDataList);

// Add your Sections to the adapter
sectionAdapter.addSection(section1);

// Set up your RecyclerView with the SectionedRecyclerViewAdapter
GridLayoutManager glm = new GridLayoutManager(getContext(), 2);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        switch(sectionAdapter.getSectionItemViewType(position)) {
            case SectionedRecyclerViewAdapter.VIEW_TYPE_HEADER:
                return 2;
            default:
                return 1;
        }
    }
});
recyclerView.setLayoutManager(glm);
recyclerView.setAdapter(sectionAdapter);
Gustavo Pagani
  • 6,583
  • 5
  • 40
  • 71
  • 1
    I get what you're saying and that is actually what I had before, having learnt from [here](http://blog.sqisland.com/2014/12/recyclerview-grid-with-header.html). That isn't what I'm after though, I actually want the `CardView` to be the section, with the elements inside just as illustrated by Google themselves, and have those `CardViews` themselves be in a `RecyclerView`. How can that be done to achieve just that same result as Google is showing? – inferKNOX Sep 08 '16 at 16:51
  • There is more simply library to support nested recycler view with custom layout manager [RendererRecyclerViewAdapter](https://github.com/vivchar/RendererRecyclerViewAdapter), see CompositeViewRenderer. Also please loot at this answer https://stackoverflow.com/a/48464993/4894238 – Vitaly Jan 26 '18 at 16:26
0

To sum up. You shouldn't use recycler inside of a recycler. You need to implement a custom gridLayoutManager. To achieve this read these:

From docs https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemDecoration.html

An ItemDecoration allows the application to add a special drawing and layout offset to specific item views from the adapter's data set. This can be useful for drawing dividers between items, highlights, visual grouping boundaries and more.

So if you use the above along with this http://blog.sqisland.com/2014/12/recyclerview-grid-with-header.html you can definitely achieve what you are looking for. Just think of the image you presented from material guidelines as a group in your gridLayoutManager.

  • You can have different types of views
  • Each row might have multiple views
  • Each row might be decorated differently
masp
  • 515
  • 1
  • 5
  • 15
  • 1
    I get what you're saying and agree that `RecyclerView` inside `RecyclerView` is wrong. However, to group them with a boundary will only achieve a similar result to the above, not the same result, as that is an actual `CardView`, not simply a grouping. The question then becomes, how do we get it from simply being groupings to actual `CardViews`? – inferKNOX Sep 09 '16 at 06:28