1

I was trying to set height of ConstraintLayout programmatically and I intended to use ConstraintLayout.LayoutParams. ConstraintLayout is a top-level layout in this XML. but I had weird experience when I set height from old to new with ConstraintLayout.LayoutParams and ClassCastException occurred.

java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to androidx.constraintlayout.widget.ConstraintLayout$LayoutParams

the detail code is below.

Dialog

private fun initLayoutSize() = with(binding) {
    dialog?.let {
        val height = getDisplayHeight(it.window!!.windowManager)
        val params = homeBottomSheetContainer.layoutParams as ConstraintLayout.LayoutParams // excpeiton here!!
        params.height = (height * 0.3).toInt()
        homeBottomSheetContainer.layoutParams = params
    }
}

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/homeBottomSheetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/basic16"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

<View
    android:id="@+id/homeBottomSheetTopView"
    android:layout_width="@dimen/basic30"
    android:layout_height="@dimen/basic03"
    android:layout_marginTop="@dimen/basic12"
    android:background="@drawable/bottomsheet_top_radius_view"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/homeBottomLottoSearchNotice"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/basic12"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"
    android:gravity="end"
    android:padding="@dimen/basic04"
    android:text="@string/ask_search"
    android:textColor="@color/black"
    android:textSize="@dimen/txt12"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@id/homeBottomSheetTopView"
    tools:visibility="invisible" />

<EditText
    android:id="@+id/homeLottoSearch"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:hint="@string/input_lotto_round"
    android:imeOptions="actionDone"
    android:inputType="number"
    android:maxLines="1"
    android:textColor="@color/black"
    android:textCursorDrawable="@drawable/shape_edittext_cursor_black"
    android:textSize="@dimen/txt12"
    android:visibility="invisible"
    app:backgroundTint="@color/black"
    app:layout_constraintBottom_toBottomOf="@id/homeBottomLottoSearchNotice"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@id/homeBottomLottoSearchNotice" />

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/homeBottomSheetLottoRV"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginTop="@dimen/basic12"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/homeBottomLottoSearchNotice"
    tools:listitem="@layout/item_lotto_all_round" />

</androidx.constraintlayout.widget.ConstraintLayout>

what happend?

I didn't use any FrameLayout in my XML and I couldn't find it anywhere. but why the android system tells me about FrameLayout? is FrameLayout a default top-level layout in Android View XML???

So, i changed the code with below one. and It worked!

private fun initLayoutSize() = with(binding) {
    dialog?.let {
        val height = getDisplayHeight(it.window!!.windowManager)
        val params = homeBottomSheetContainer.layoutParams as FrameLayout.LayoutParams // change here!!
        params.height = (height * 0.3).toInt()
        homeBottomSheetContainer.layoutParams = params
    }
}

But I'm so confused now. anyone help? and thank you in advance. :)

CodingBruceLee
  • 657
  • 1
  • 5
  • 19

1 Answers1

2

if you are setting only height then you may use more general ViewGroup.LayoutParams. all layout params are extending it, so there is no chance for class cast, no matter of parent

val params = homeBottomSheetContainer.layoutParams as ViewGroup.LayoutParams

besides that you may use is keyword for checking instance type

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • You're right but i still wonder why the android system tells me about FrameLayout$LayourParams not ViewGroup$LayoutParams. – CodingBruceLee Jan 24 '22 at 06:17
  • thats because "original" layout params are these from `FrameLayout` and you are trying to cast it to some other type. `ViewGroup` params are base for all other, but stacktrace doesn't know that you are casting and setting only height or width, thats just wrong casting no matter if this is root of layout or child of `RecyclerView` item – snachmsm Jan 24 '22 at 17:17