LayoutParams type changed at runtime. ClassCastException: ViewGroup$LayoutParams cannot be cast to ViewGroup$MarginLayoutParams

Viewed 320

I try to set layout params programmatically. In my fragment in onCreate method, I set LayoutParams of the ScrollView and it works. But also, I have an observer and in this observer when some condition is true I change layout params of this ScrollView again. But the problem is that the same code which is in onCreate doesn't work in an observer. Below is a fragment of onCreate method when I set layout params and set an observer. The method which changes layout params is copy-pasted so it is a little strange why it is working and a milliseconds after doesn't.

onCreate:

Log.d("Setting height in onCreate method")
binding.scrollRoot.layoutParams = ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT,
    binding.txtCars.lineHeight * SIZE + 10
)


cars.observe(viewLifecycleOwner, Observer {
    if (it.size < SIZE)
    {
        Log.d("Setting height in observer method")
        binding.scrollRoot.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            binding.txtCars.lineHeight * (it.size) + 10
        )
    }
    binding.txtCars.text = formatCars(it, requireContext())
})

Logcat:

D/AppDebug: Setting height in onCreate method
D/AppDebug: Setting height in observer method
I/zygote64: Method exceeds compiler instruction limit: 25337 in void org.ccil.cowan.tagsoup.HTMLSchema.<init>()
D/AndroidRuntime: Shutting down ViewModel
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.fuelmanager, PID: 8034
    java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.view.ViewGroup$MarginLayoutParams
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6662)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22216)
        at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22216)
        at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1156)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:403)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1539)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:823)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:702)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6671)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:831)
        at android.view.View.measure(View.java:22216)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2596)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1638)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1892)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1522)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7292)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:981)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:721)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:967)
        at android.os.Handler.handleCallback(Handler.java:808)
        at android.os.Handler.dispatchMessage(Handler.java:101)
        at android.os.Looper.loop(Looper.java:166)
        at android.app.ActivityThread.main(ActivityThread.java:7529)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

After research, I found this question

Here you're replacing existing layout params of correct type AbsListView.LayoutParams with more generic ViewGroup.LayoutParams. Layout params type is that of the parent container of the view.
If you need to modify existing layout params, access them with getLayoutParams(), modify it, and call requestLayout() to notify that the layout has changed.

So I made it in that way:

Log.d("Setting height in observer method")
val layoutParams = binding.scrollRoot.layoutParams
layoutParams.height = binding.txtCars.lineHeight * (it.size) + 10

And it works.

But my question is how is it possible that type of ViewGroup/ScrollView LayoutParams changed. What happened after onCrete() that makes this error in the observer?

0 Answers
Related