luizgrp / SectionedRecyclerViewAdapter

An Adapter that allows a RecyclerView to be split into Sections with headers and/or footers. Each Section can have its state controlled individually.
MIT License
1.68k stars 372 forks source link

Provide a better way to access the rootView of each Section #95

Closed hgg closed 6 years ago

hgg commented 6 years ago
Current Situation

Imagine you want to do something with each sections' view. For instance, changing it's background color. Since no XML is given by the user of the lib to serve as the section layout, the only way to do this would be programmatically. Currently, the only way to access the root view for each section is through something like this:

public RecyclerView.ViewHolder getItemViewHolder(View view) {
        View rootView = view.getRootView();
        // Do stuff with the rootView
        return new ViewHolder(view);

However, this is a terrible way to access the root view of the section, since for every ItemViewHolder created, some amount of unnecessary code will be run. Even using this method, the result is not quite as I expected, as I'm getting the following result instead of an even rectangle. I believe this is because I'm getting the rootView of the item and not of the section. Also tried chaining getRootView()calls, but I get the same view no matter how many times I chain it.

image

I ended up creating dummy. invisible items that I use as placeholders to fill the empty space. However, this solution ended up polluting the code and is hardly elegant. So if you have any better idea on how to do this, I'd love to hear it.

Proposed Situation

My first proposal to solve this situation, which I don't know if it is possible, is to have a method on the Section class that returns the rootView of the section, allowing the user of library to simply call this on the Section's constructor and programmatically change whatever he'd like.

public View getSectionRootView()

Also a new builder method could be introduced to override the default view for the section, something like:

new SectionParameters.Builder(R.layout.allapps_app)
                .headerResourceId(R.layout.header)
                .footerResourceId(R.layout.footer)
                // New method
                .sectionResourceId(R.layout.section)
                .build());

EDIT: Added some more considerations to the current situation section.

luizgrp commented 6 years ago

Hi @Hugainz,

Thanks for the detailed description of your suggestion.

I'm afraid I don't see a possible way of having access to the "root view" of the whole section, as it doesn't exist. There isn't a single view for the whole section, if there was, it would defeat the concept of recycling views. Section is a concept created by the library to "group" the views displayed in the RecyclerView, but the views are still separated.

The current situation that you explained is the expected situation: you have a row span of 4 items, you have 5 items, so on the second row it displays 1 item and the other 3 items are missing.

I see few ways of trying to tackle the 'issue':

  1. Create dummy items for the remaining 3 items, as you described.
  2. Change the layout manager back to linear and for each section item you have a layout that can display 4 icons (first item displays calculator, calendar, camera, chrome, second item displays clock and set visibility of other icons to invisible). Thus you can access the root view of each row and change the background colour. The advantage in relation to the previous option is that you don't have to create dummy items. I would go this way.
  3. Have a single content in the section, which displays all the icons using a proper layout (GridLayout?). I wouldn't recommend going that way if you are going to display many icons per section, otherwise it would render all the icons of the section in one go, even the ones not displayed (that don't fit in the screen), and it won't recycle the views properly.

Let me know if you need more clarification.

hgg commented 6 years ago

Hi @luizgrp.

Thanks for your answer and clarifications. I now clearly understand why what I'm asking is not possible. I'll try to implement your suggestion, as creating the dummy icons and setting each icon background every time each item view is bound is really bad for performance.

Thanks again :+1: