BottomSheetDialog with ConstraintLayout containing NestedScrollView having height match_constraint rendered with actual 0px height
Asked Answered
O

0

8

I have a very simple layout that I need to render into a BottomSheetDialog. The layout is just a scrolling view containing just TextViews and a button below the scrolling view (so the button is fixed at the bottom and always visible.) This is just a distilled version of what's in my app, but it will suffice to explain the problem:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.core.widget.NestedScrollView
            android:id="@+id/nestedScrollView"
            android:fillViewport="true"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toTopOf="@id/ok_button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

                <TextView
                    android:id="@+id/fine_print_header"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="16dp"
                    android:layout_marginLeft="16dp"
                    android:layout_marginTop="32dp"
                    android:layout_marginEnd="16dp"
                    android:gravity="center_horizontal"
                    android:text="Fine Print"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

                <TextView
                    android:id="@+id/fine_print_copy"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="16dp"
                    android:layout_marginLeft="16dp"
                    android:layout_marginTop="32dp"
                    android:layout_marginEnd="16dp"
                    android:text="This is the fine print. It's very detailed. So many carefully crafted details"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@id/fine_print_header"/>

            </androidx.constraintlayout.widget.ConstraintLayout>
        </androidx.core.widget.NestedScrollView>
        <Button
            android:id="@+id/ok_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="16dp"
            android:layout_marginVertical="16dp"
            android:text="OK"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/nestedScrollView"/>
    </androidx.constraintlayout.widget.ConstraintLayout>>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Here is how I present the layout in my Fragment code:

            val contentView = requireActivity().layoutInflater.inflate(R.layout.bottom_sheet_dialog, null)
            val bottomSheetDialog = BottomSheetDialog(requireContext())
            bottomSheetDialog.setContentView(contentView)
            bottomSheetDialog.show()

What I am expecting to see is what is in the preview in Android Studio:

Android Studio Preview

What I actually see is this:

Application screen capture

If I step in with Layout Inspector, I can see that the NestedScrollView is really there, but it is rendered with height 0px. It's as if the constraint layout tooling ignored the whole match_constraint idea and really rendered things as if I called for 0dp. If I use match_parent it will render behind the button; if I use wrap_content the preview shows it rendering outside the bounds. If I set an actual size (e.g. 80dp) then it will appear: but this is not a scalable solution – I should be able to use match_constraint here!

I tried all the relevant combinations of top:bottom constraint relationships between the NestedScrollView and the Button, tried with and without android:fillViewPort="true", tried with and without app:layout_behavior=“@string/appbar_scrolling_view_behavior”, tried without using a CoordinatorLayout as the top layout (using a ConstraintLayout at the top instead) – none of these have ANY effect whatsoever.

Anyone know how to deal with this?

UPDATE:

I was able to make something work (without having to "concede defeat" and switch to RelativeLayout.) On the NestedScrollView I set:

            android:layout_height="wrap_content"
            app:layout_constrainedHeight="true"

and now it renders correctly in both the preview and the device.

I would still like to know why MATCH_CONSTRAINT isn't working in this context.

Opulent answered 15/12, 2020 at 23:1 Comment(1)
This is maybe not the issue, but your inner ConstraintLayout has dimensions of match_parent which can produce unpredictably results. You should use 0dp and the appropriate constraints instead. The doc says as much explicitly if you care to search for it. There should be lint rule for that.Epirus

© 2022 - 2024 — McMap. All rights reserved.