jplabs
jplabs

Reputation: 131

Android nested RecyclerView with LinearLayoutManager and FlexboxLayoutManager not working properly

I am facing multiple challenges while trying to develop a search result filter page. The search results can be filtered with a selection of multiple filters per filter category. There can be up to 30+ filter categories and each of them can have up to 100+ filters but it depends heavily on the search term. I implemented a vertical RecyclerView with multiple nested horizontal RecyclerViews per filter category. Each nested RecyclerView contains a list of Chips which can be toggled. The list updates itself after the selected filter changes. This functionality works quite fine. Because of the dynamic count of filters which can be quite high, the requirement is to make the horizontal RecyclerViews expandable/collapsible so that the scrolling is disabled and the filters Chips wrap themselves in new lines. I achieved this with the usage of the FlexboxLayoutManager from the flexbox library from Google.

    private fun getLinearLayoutManager(expanded: Boolean): LayoutManager {
        val context = binding.root.context
        return if (expanded) FlexboxLayoutManager(
            context, FlexDirection.ROW, FlexWrap.WRAP
        ) else LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
    }
    private fun onExpandCollapseClick(section: AfterSearchFilterSection, holder: ViewHolder) {
        val expanded = expandedSections[section.title] ?: false
        expandedSections[section.title] = !expanded
        if (!expanded) {
            saveScrollState(holder, section.filterName)
        }
        notifyItemChanged(holder.adapterPosition)
    }

The layout looks like below: collapsed filters expanded filters

This implementation brings some issues:

The scrolling performance is really bad when scrolling vertically with multiple expanded filter categories. I tried to use a shared RecycledViewPool for the nested RecyclerViews, but then the app crashes when I expand a filter category. Probably because of the switch to a different LayoutManager

java.lang.ClassCastException: androidx.recyclerview.widget.RecyclerView$LayoutParams cannot be cast to com.google.android.flexbox.FlexItem
                                                                                                        at com.google.android.flexbox.FlexboxHelper.calculateFlexLines(FlexboxHelper.java:447)
                                                                                                        at com.google.android.flexbox.FlexboxHelper.calculateHorizontalFlexLines(FlexboxHelper.java:249)
                                                                                                        at com.google.android.flexbox.FlexboxLayoutManager.updateFlexLines(FlexboxLayoutManager.java:960)
                                                                                                        at com.google.android.flexbox.FlexboxLayoutManager.onLayoutChildren(FlexboxLayoutManager.java:737)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3686)
                                                                                                        at android.view.View.measure(View.java:26358)

Even if I would fix this issue I am facing another challenge where the FlexboxLayoutManager cuts some items if the RecyclerView gets to high. There are multiple github issues open like here and here.

Are there any ideas, how I could achieve the required layout with smooth performance and without crashes and bugs?

I tried to use RecycledViewPools. Another alternative is to use a ChipGroup in a HorizontalScrollView which gets moved to a LinearLayout on expand/collapse. But here I would loose the RecyclerView benefits and performance wouldn't be great either.

I searched for alternative LayoutManagers and libraries to achieve a flexbox wrapping in a RecylerView but the only solutions I found are the FlexboxLayoutManager and the ChipGroup (which is not usable in a RecyclerView)

Upvotes: 1

Views: 321

Answers (0)

Related Questions