Search code examples
androidandroid-flexboxlayout

Crash when dynamically change LayoutManager to FlexboxLayoutManager


I have to use both LinearLayoutManager or FlexbotLayoutManager depends on childs size in RecyclerView.

When I change LinearLayoutManager to FlexbotLayoutManager dynamically like:

recyclerView.layoutManager = 
            FlexibleFlexboxLayoutManager(context).apply {
                    flexWrap = FlexWrap.NOWRAP
                    flexDirection = FlexDirection.ROW
            }

I face that error:

java.lang.ClassCastException: android.support.v7.widget.RecyclerView$LayoutParams cannot be cast to com.google.android.flexbox.FlexItem at com.google.android.flexbox.FlexboxHelper.calculateFlexLines(FlexboxHelper.java:439) at com.google.android.flexbox.FlexboxHelper.calculateHorizontalFlexLines(FlexboxHelper.java:243) at com.google.android.flexbox.FlexboxLayoutManager.updateFlexLines(FlexboxLayoutManager.java:955) at com.google.android.flexbox.FlexboxLayoutManager.onLayoutChildren(FlexboxLayoutManager.java:731) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924) at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3336) at android.view.View.measure(View.java:22071)

How can it be fixed?


Solution

  • The problem is that FlexboxLayoutManager overrides only generateLayoutParams(Context c, AttributeSet attrs) but does not override generateLayoutParams(ViewGroup.LayoutParams lp)

    So solution is implementing that method:

    class SafeFlexboxLayoutManager : FlexboxLayoutManager {
    
        constructor(context: Context) : super(context)
    
        constructor(context: Context, flexDirection: Int) : super(context, flexDirection)
    
        constructor(context: Context, flexDirection: Int, flexWrap: Int) : super(context, flexDirection, flexWrap)
    
        constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(
            context,
            attrs,
            defStyleAttr,
            defStyleRes
        )
    
        override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {
            return FlexboxLayoutManager.LayoutParams(lp)
        }
    }