0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FlexboxLayoutManagerで発生するClassCastExceptionの解決方法

Last updated at Posted at 2019-07-04

FlexboxLayoutManagerとは

FlexboxLayoutについては以下の記事に簡単にまとめています。
幅が足りない時に自動で折り返すレイアウトを探してたら、FlexboxLayoutがドンピシャだった

エラーの概要

RecyclerViewでFlexboxLayoutManagerを使用する時に発生したエラーのお話です。
まずはエラーログ

    E/AndroidRuntime: FATAL EXCEPTION: main
    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.FlexboxLayoutManager.updateFlexLines(FlexboxLayoutManager.java:949)
        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:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:401)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:721)
        at android.view.View.measure(View.java:22002)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2410)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1498)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1751)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:723)
        at android.view.Choreographer.doFrame(Choreographer.java:658)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

一つのRecyclerViewで、状況に応じてFlexboxLayoutManagerとLinearLayoutManagerを使い分けるといった少しトリッキーな使い方をしていました。
LinearLayoutManagerを設定したViewの表示後、FlexboxLayoutManagerを設定したViewを表示しようとしたときに発生したエラーです。

解決方法

以下のようにFlexboxLayoutManagerのWrapperクラスを作ってやれば回避可能です。
FlexboxLayoutManagerではgenerateLayoutParams(c: Context, attrs: AttributeSet)は継承されていますが、
generateLayoutParams(lp: ViewGroup.LayoutParams)がありません。
呼び出し元によってはLayoutParamsが必要となりキャストエラーが発生しているようです。
具体的な条件は精査できていないため参考までに留めてください。

FlexboxLayoutManagerWrapper.kt
class FlexboxLayoutManagerWrapper(val context: Context) : FlexboxLayoutManager(context) {
    override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {
        return LayoutParams(lp)
    }
}
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val layoutManager = FlexboxLayoutManagerWrapper(this)
        layoutManager.flexDirection = FlexDirection.ROW
        layoutManager.flexWrap = FlexWrap.WRAP
        layoutManager.justifyContent = JustifyContent.FLEX_START

        recycler_view_list.layoutManager = layoutManager
    }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?