constraintlayout wraps its content width with children match_constraint

依然范特西╮ 提交于 2019-12-24 18:50:31

问题


I have a simple side bar with 2 buttons vertical chained and i want my side bar to wrap largest button while smaller button expands to match largest one. Here is a capture where i want "AAA" button to match "VALIDATE" button width

Of course what poped my mind is to use match contraint width for both buttons but when using a wrap_content container this leads to:

my layout :

<?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/container"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:background="?attr/colorSurface"
    android:padding="@dimen/screen_padding">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/redo_button"
        style="@style/AppStyle.Button.OutlinedButton.SecondaryVariantStroke"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/spacing_normal"
        android:text="aaa"
        app:layout_constrainedWidth="false"
        app:layout_constraintBottom_toTopOf="@+id/validate_button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <ImageView
        android:layout_width="32dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:background="@drawable/shape_circle_secondary_variant"
        android:padding="7dp"
        android:src="@drawable/ic_camera"
        android:tint="@android:color/white"
        app:layout_constraintBottom_toBottomOf="@+id/redo_button"
        app:layout_constraintDimensionRatio="h,1:1"
        app:layout_constraintEnd_toEndOf="@+id/redo_button"
        app:layout_constraintStart_toEndOf="@+id/redo_button"
        app:layout_constraintTop_toTopOf="@+id/redo_button"
        tools:ignore="ContentDescription" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/validate_button"
        style="@style/AppStyle.Button.OutlinedButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/global_valid"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/redo_button" />

</androidx.constraintlayout.widget.ConstraintLayout>

回答1:


If you know which button is going to be wider, then you can make that button wrap_content and constrain the other button to it as follows:

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/container"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:background="@android:color/darker_gray"
    android:padding="16dp">

    <Button
        android:id="@+id/redo_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="aaa"
        app:layout_constrainedWidth="false"
        app:layout_constraintBottom_toTopOf="@+id/validate_button"
        app:layout_constraintEnd_toEndOf="@+id/validate_button"
        app:layout_constraintStart_toStartOf="@+id/validate_button"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <Button
        android:id="@+id/validate_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Validate"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/redo_button" />


</androidx.constraintlayout.widget.ConstraintLayout>

If this solves your problem, stop here.

Things get a little more complicated if you don't know in advance which button will be wider. (Maybe due to language changes.) In that case, you can check the sizes programmatically and explicitly expand the narrower button. You may consider this less than ideal.

As for accomplishing this in XML, I have looked at this type of problem in the past and the problem always reduces to some kind of circular reference issue. (In fact, this is the problem that you are having with match_constraints widgets in a wrap_content container. The widgets are as wide as the container and the container is as wide as the widgets! What?)

If you don't know which button will be wider, you can create an invisible button that has two lines of text that correspond to the labels of your buttons (assuming single line labels.)

Now that there is a dummy button that is the right width, constrain the sides of your buttons to the sides of the dummy button and make their width match_constraints.

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/container"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:background="@android:color/darker_gray"
    android:padding="16dp">

    <Button
        android:id="@+id/dummyForSizing"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="aaa\nValidate"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/redo_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="aaa"
        app:layout_constrainedWidth="false"
        app:layout_constraintBottom_toTopOf="@+id/validate_button"
        app:layout_constraintEnd_toEndOf="@+id/dummyForSizing"
        app:layout_constraintStart_toStartOf="@+id/dummyForSizing"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <Button
        android:id="@+id/validate_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Validate"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/dummyForSizing"
        app:layout_constraintStart_toStartOf="@+id/dummyForSizing"
        app:layout_constraintTop_toBottomOf="@+id/redo_button" />


</androidx.constraintlayout.widget.ConstraintLayout>

You would, of course, make the dummy button invisible.



来源:https://stackoverflow.com/questions/53485425/constraintlayout-wraps-its-content-width-with-children-match-constraint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!