Search code examples
androidandroid-layoutandroid-viewandroid-constraintlayoutandroid-layoutparams

Top-level Layout in Android XML is ALWAYS FrameLayout?


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. :)


Solution

  • 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