Search code examples
androidandroid-viewlayoutparams

Android, does layoutParams points on parent view and not the view itself?


I got a problem when trying to update dynamically the layoutParams of a view.

The view to update is a ConstraintLayout, and I want to dynamically change it's app:layout_constraintDimensionRatio property.

The fragment XML :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LevelFragment">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/board"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="32dp"
            android:layout_marginEnd="32dp"
            android:layout_marginTop="32dp"
            android:layout_marginBottom="32dp"
            android:background="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

        </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

But when I try to change it from Kotlin fragment code

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    board = view.findViewById(R.id.board)
    // Set ratio
    val layoutParams = board!!.layoutParams as ConstraintLayout.LayoutParams
    layoutParams.dimensionRatio = "5:1"
    board!!.layoutParams = layoutParams
}

It fails with this error after debug build :

android.widget.FrameLayout$LayoutParams cannot be cast to androidx.constraintlayout.widget.ConstraintLayout$LayoutParams

So, I'm wondering why it complains about FrameLayout to ConstraintLayout cast, because the layoutParams is taken from the board View, which is a ConstraintLayout...

Does the paramsLayout refers to the parent view and not the view itself ?

And if so, how to update view dimensionRatio property ?

Thanks !


Solution

  • LayoutParams are the parameters which parent ViewGroup uses to layout its children. Each child has its own LayoutParams which has a specific type based on type of its parent. i.e. children of FrameLayout has FrameLayout.LayoutParams as their LayoutParams and children of LinearLayout has LinearLayout.LayoutParams as their LayoutParams and so on. Also they can not get cast to each other, it means you can not cast LinearLayout.LayoutParams to FrameLayout.LayoutParams since they have different implementation of LayoutParams. But all of LayoutParams have exteded ViewGroup.LayoutParams, so it is safe to cast them to ViewGroup.LayoutParams.
    In your case you are casting board.layoutParams to ConstraintLayout.LayoutParams but since parent of board is a FrameLayout then its LayoutParams is of type FrameLayout.LayoutParams and can not get cast to ConstraintLayout.LayoutParams.
    If you want to fix this you have to replace parent of board which is a FrameLayout with a ConstraintLayout.
    Also you can read here if you want to see how LayoutParams works.