0

I have such XML file for custom Dialog:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:paddingHorizontal="15dp"
    android:paddingVertical="10dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cl_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:paddingBottom="15dp">

        <TextView
            style="@style/tv_big"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="@id/cl_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:text="Filter"/>
        <com.google.android.material.button.MaterialButton
            android:id="@+id/bt_reset"
            android:textColor="@color/black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/Widget.MaterialComponents.Button.OutlinedButton"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="@id/cl_header"
            android:text="RESET FILTERS"/>
    </androidx.constraintlayout.widget.ConstraintLayout>


    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cl_distance"
        app:layout_constraintTop_toBottomOf="@id/cl_header"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_distance_title"
            style="@style/tv_medium"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Distance range"/>

        <TextView
            android:id="@+id/tv_distance_result"
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            app:layout_constraintBottom_toBottomOf="@id/tv_distance_title"
            app:layout_constraintLeft_toRightOf="@id/tv_distance_title"
            app:layout_constraintRight_toRightOf="parent"
            android:background="#ddd"
            android:padding="3dp"
            android:textColor="#333"
            android:text="0 km - 500km"/>

        <com.google.android.material.slider.RangeSlider
            android:id="@+id/slider_distance"
            app:layout_constraintTop_toBottomOf="@id/tv_distance_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:labelBehavior="gone"
            android:stepSize="1.0" />
    </androidx.constraintlayout.widget.ConstraintLayout>


    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cl_location"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/cl_distance"
        app:layout_constraintStart_toStartOf="parent">

        <TextView
            android:id="@+id/tv_location_title"
            style="@style/tv_medium"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Location"/>
        <EditText
            android:id="@+id/et_location"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            app:layout_constraintTop_toBottomOf="@id/tv_location_title"
            android:hint="@string/filter_location_et_hint" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/cl_location"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bt_cancel"
            android:backgroundTint="#ccc"
            android:textColor="@color/black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:text="CANCEL"/>
        <Button
            android:id="@+id/bt_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="save"
            android:layout_marginHorizontal="20dp"/>
    </LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

Android Studio renders it in this way:

view from android studio

And this is what I want to have in my Dialog.

BUT:

On physical device and on emulator it looks different than in Android Studio:

view during app working

My question is: how to place "Filter" title on the left, and make the location EditText matching the parent (in the working app)?

James121
  • 81
  • 10
  • 1
    You would have to use either RelativeLayout (use android:layout_toLeftOf) or LinearLayout (set its orientation to horizontal and set weights). – David Lee Jun 23 '21 at 14:51
  • 1
    Unrelated to this answer, but the whole point of ConstraintLayout is to remove these nested layouts that you have. If you're going to nest multiple ConstraintLayouts, then just use LinearLayouts. You can literally design this whole dialog in one single ConstraintLayout. – Vedprakash Wagh Jun 23 '21 at 14:53
  • By the way, why have you used so much nesting? I believe that only one constraint layout is enough for the job. – Shreemaan Abhishek Jun 23 '21 at 14:54
  • Here's a [link](https://pastebin.com/z1aYhedZ) to a better layout code, maybe this might help you. And yes, please consider tweaking some margins and stuff according to your choice :) – Shreemaan Abhishek Jun 23 '21 at 15:08

2 Answers2

0

What everybody else said is correct, keeping your layout flat is good for both performance and for these situations where you want to quickly figure out why isn't the layout being laid out the way you wanted it ;)

Try this :

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingHorizontal="15dp"
    android:paddingVertical="10dp">

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="start"
        android:text="Filter"
        app:layout_constraintBottom_toBottomOf="@id/bt_reset"
        app:layout_constraintEnd_toStartOf="@id/bt_reset"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/bt_reset" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/bt_reset"
        style="@style/Widget.MaterialComponents.Button.OutlinedButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="RESET FILTERS"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/tv_distance_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Distance range"
        app:layout_constraintBottom_toBottomOf="@id/tv_distance_result"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/tv_distance_result" />

    <TextView
        android:id="@+id/tv_distance_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:background="#ddd"
        android:gravity="center"
        android:paddingHorizontal="18dp"
        android:paddingVertical="3dp"
        android:text="0 km - 500km"
        android:textColor="#333"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/bt_reset" />

    <com.google.android.material.slider.RangeSlider
        android:id="@+id/slider_distance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stepSize="1.0"
        app:labelBehavior="gone"
        app:layout_constraintTop_toBottomOf="@id/tv_distance_result" />

    <TextView
        android:id="@+id/tv_location_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Location"
        app:layout_constraintTop_toBottomOf="@id/slider_distance" />

    <EditText
        android:id="@+id/et_location"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="test"
        app:layout_constraintTop_toBottomOf="@id/tv_location_title" />

    <Button
        android:id="@+id/bt_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="20dp"
        android:backgroundTint="#ccc"
        android:text="CANCEL"
        android:textColor="@color/colorBlack"
        app:layout_constraintEnd_toStartOf="@id/bt_save"
        app:layout_constraintTop_toBottomOf="@id/et_location" />

    <Button
        android:id="@+id/bt_save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="20dp"
        android:text="save"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/et_location" />

</androidx.constraintlayout.widget.ConstraintLayout>
Reza Mohammadi
  • 106
  • 1
  • 1
  • 6
  • Your solution almost works, but there is an issue with LinearLayout about which I write in my answer (I found the solution in the meantime) – James121 Jun 23 '21 at 18:41
0

I changed inner ConstraintLayouts into LinearLayouts and used weights. I also used this trick to fill space between e.g. "Filter" title and "reset filters" button.

There was also an issue with ll_location LinearLayout - it didn't match the parent. I replaced:

<LinearLayout
        android:id="@+id/ll_location"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/ll_distance_ext"
        android:orientation="vertical">

        <!--  content  -->

</LinearLayout>

into:

<LinearLayout
        android:id="@+id/ll_location"

        android:layout_width="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"

        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/ll_distance_ext"
        android:orientation="vertical">

        <!--  content  -->

</LinearLayout>

And then it worked.

The reason why I don't want to use flat layout (why I use nested layouts) is that IMHO the flat layout makes the code more difficult to maintain. When you have Views splited into groups you can easily replace them, no matter how many View there are in a group.

My solution:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:paddingHorizontal="15dp"
    android:paddingVertical="10dp">

    <LinearLayout
        android:id="@+id/ll_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:paddingBottom="15dp">

        <TextView
            style="@style/tv_big"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:text="Filter"/>
        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/bt_reset"
            android:textColor="@color/black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/Widget.MaterialComponents.Button.OutlinedButton"
            android:text="reset filters"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_distance_ext"
        app:layout_constraintTop_toBottomOf="@id/ll_header"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_distance_title"
                style="@style/tv_medium"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Distance range"/>

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <TextView
                android:id="@+id/tv_distance_result"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:textAlignment="center"
                android:background="#ddd"
                android:padding="3dp"
                android:textColor="#333"
                android:text="0 km - 500km"/>

        </LinearLayout>

        <com.google.android.material.slider.RangeSlider
            android:id="@+id/slider_distance"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:labelBehavior="gone"
            android:stepSize="1.0" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_location"
        android:layout_width="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/ll_distance_ext"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_location_title"
            style="@style/tv_medium"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Location"/>
        <EditText
            android:id="@+id/et_location"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:hint="@string/filter_location_et_hint" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/ll_location"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bt_cancel"
            android:backgroundTint="#ccc"
            android:textColor="@color/black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:text="cancel"/>
        <Button
            android:id="@+id/bt_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="save"
            android:layout_marginHorizontal="20dp"/>
    </LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>
James121
  • 81
  • 10
  • I don't know about difficulty in maintenance but it has noticeable impact on performance. Not only nested view hierarchy and too many ViewGroup but also additional costs that some of them have like horizontal LinearLayout that results in [double layout taxation](https://developer.android.com/topic/performance/rendering/optimizing-view-hierarchies#double). – Reza Mohammadi Jun 23 '21 at 21:28