Espaciado uniforme de vistas usando ConstraintLayout

Respuestas:

323

Hay dos formas de lograr esto usando ConstraintLayout: Cadenas y Pautas . Para usar Chains, asegúrese de estar usando ConstraintLayoutBeta 3 o más reciente y si desea usar el editor de diseño visual en Android Studio, asegúrese de estar usando Android Studio 2.3 Beta 1 o más reciente.

Método 1 - Usando cadenas

Abra el editor de diseño y agregue sus widgets de manera normal, agregando restricciones principales según sea necesario. En este caso, he agregado dos botones con restricciones en la parte inferior del padre y el lado del padre (lado izquierdo para el botón Guardar y lado derecho para el botón Compartir):

ingrese la descripción de la imagen aquí

Tenga en cuenta que en este estado, si volteo a la vista horizontal, las vistas no llenan el padre sino que están ancladas a las esquinas:

ingrese la descripción de la imagen aquí

Resalte ambas vistas, ya sea haciendo clic con Ctrl / Cmd o arrastrando un cuadro alrededor de las vistas:

ingrese la descripción de la imagen aquí

Luego haga clic derecho en las vistas y elija "Centrar horizontalmente":

ingrese la descripción de la imagen aquí

Esto establece una conexión bidireccional entre las vistas (que es cómo se define una cadena). Por defecto, el estilo de cadena es "spread", que se aplica incluso cuando no se incluye ningún atributo XML. Siguiendo con este estilo de cadena pero configurando el ancho de nuestras vistas para permitir que 0dplas vistas llenen el espacio disponible, extendiéndose uniformemente entre los padres:

ingrese la descripción de la imagen aquí

Esto es más notable en la vista horizontal:

ingrese la descripción de la imagen aquí

Si prefiere omitir el editor de diseño, el XML resultante se verá así:

<android.support.constraint.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">

<Button
    android:id="@+id/button_save"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="@string/button_save_text"
    android:layout_marginStart="8dp"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="4dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/button_share"
    app:layout_constraintHorizontal_chainStyle="spread" />

<Button
    android:id="@+id/button_share"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="@string/button_share_text"
    android:layout_marginStart="4dp"
    android:layout_marginEnd="8dp"
    android:layout_marginBottom="8dp"
    app:layout_constraintLeft_toRightOf="@+id/button_save"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

Detalles:

  • establecer el ancho de cada elemento 0dpo MATCH_CONSTRAINTpermite que las vistas llenen el elemento primario (opcional)
  • las vistas deben estar unidas bidireccionalmente (a la derecha de los enlaces del botón Guardar para compartir, a la izquierda de los enlaces del botón Compartir para guardar el botón), esto sucederá automáticamente a través del editor de diseño al elegir "Centrar horizontalmente"
  • la primera vista en la cadena puede especificar el estilo de la cadena a través de layout_constraintHorizontal_chainStyle, consulte la documentación de varios estilos de cadena, si el estilo de la cadena se omite, el valor predeterminado es "propagación"
  • La ponderación de la cadena se puede ajustar a través de layout_constraintHorizontal_weight
  • este ejemplo es para una cadena horizontal, hay atributos correspondientes para cadenas verticales

Método 2: uso de una directriz

Abra su diseño en el editor y haga clic en el botón de la guía:

ingrese la descripción de la imagen aquí

Luego seleccione "Agregar directriz vertical": ingrese la descripción de la imagen aquí

Aparecerá una nueva directriz, que de forma predeterminada, probablemente estará anclada a la izquierda en valores relativos (indicados por la flecha hacia la izquierda):

guía relativa del editor de diseño

Haga clic en la flecha hacia la izquierda para cambiarlo a un valor porcentual, luego arrastre la guía a la marca del 50%:

guía de porcentaje del editor de diseño

La guía ahora se puede usar como un ancla para otras vistas. En mi ejemplo, adjunté la derecha del botón Guardar y la izquierda del botón Compartir a la guía:

diseño final

Si desea que las vistas llenen el espacio disponible, entonces la restricción debe establecerse en "Cualquier tamaño" (las líneas onduladas que se ejecutan horizontalmente):

cualquier restricción de tamaño

(Esto es lo mismo que configurar el layout_widtha 0dp).

También se puede crear una guía en XML con bastante facilidad en lugar de usar el editor de diseño:

<android.support.constraint.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/guideline"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />
AdamK
fuente
1
No pude encontrar una manera de crear una guía con una restricción. Quiero que una directriz horizontal esté en el medio de dos vistas. Imagine una vista más grande con 100dp de altura en la parte superior y una más pequeña con 50dp de altura en la parte inferior. Quiero colocar una directriz en el medio del espacio entre ellos.
headsvk
3
No creo que pueda agregar restricciones a la guía en sí. Puede agregar varias pautas y luego restringir las vistas a esas pautas. Es posible que desee publicar una nueva pregunta con detalles sobre lo que está tratando de lograr. Siéntase libre de pegarlo aquí también.
AdamK
Gracias querido señor. Fue una ayuda oportuna y efectiva.
iSofia
Quiero dar un ancho proporcional a las vistas. Por ejemplo, quiero que el botón compartir tenga el doble de ancho que el botón guardar. Sin usar pautas ya que mis puntos de vista no se colocan uno al lado del otro como en este ejemplo. ¿Es posible?
Shubham Naik, el
Debe convertir los valores dados por las pautas en márgenes o rellenos reales. Las directrices funcionan solo en el modo de diseño.
Abhinav Saxena
49

Para crear 2 vistas en la misma línea, igual ancho, solo necesita definir

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <Button
        android:id="@+id/button1"
        android:layout_width="0dp"  
        android:layout_height="wrap_content"
        android:text="Button 1"
        app:layout_constraintEnd_toStartOf="@+id/button2"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/button1" />

</android.support.constraint.ConstraintLayout>

Nota

  • ancho = 0dp ( MATCH_CONSTRAINT)
  • Restricción de button1y button2debe gustar arriba

Resultado

MÁS
Si quieres View1más grande de lo View2que puedes usar weighto percent.
Ejemplo, View1ancho = 2 * View2ancho usa peso

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 3"
        app:layout_constraintEnd_toStartOf="@+id/button4"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintStart_toStartOf="parent"
        />

    <Button
        android:id="@+id/button4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 4"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/button3"
        />

</android.support.constraint.ConstraintLayout>

Resultado

Ejemplo, View1ancho = 2 * View2ancho usa porcentaje

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <Button
        android:id="@+id/button5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 5"
        app:layout_constraintEnd_toStartOf="@+id/button6"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintWidth_percent="0.667"
        />

    <Button
        android:id="@+id/button6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 6"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/button5"
        app:layout_constraintWidth_percent="0.333"
        />

</android.support.constraint.ConstraintLayout>

Resultado

Phan Van Linh
fuente
23

Bueno si ayuda a alguien

la clave está aquí app:layout_constraintHorizontal_weight="1"y
lo mejor del diseño de restricción es que admite la dependencia circular y esto es lo que he hecho usando exactamente eso.

Para el primer hijo
app:layout_constraintEnd_toStartOf="@+id/textInputSecondChild"

Para el segundo hijo

app:layout_constraintLeft_toRightOf="@+id/textInputFirstChild"

aquí está la demo completa

<android.support.design.widget.TextInputLayout
    android:id="@+id/textInputParent"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent">

    <EditText
        android:id="@+id/editTextParent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/state" />
</android.support.design.widget.TextInputLayout>

<android.support.design.widget.TextInputLayout
    android:id="@+id/textInputFirstChild"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toStartOf="@+id/textInputSecondChild"
    app:layout_constraintHorizontal_weight="1"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textInputParent">

    <EditText
        android:id="@+id/editTextChildOne"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/pin_code" />
</android.support.design.widget.TextInputLayout>

<android.support.design.widget.TextInputLayout
    android:id="@+id/textInputSecondChild"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintHorizontal_weight="1"
    app:layout_constraintLeft_toRightOf="@+id/textInputFirstChild"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textInputParent">

    <EditText
        android:id="@+id/editTextChildSecond"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/country" />
</android.support.design.widget.TextInputLayout>
novatodeveloper
fuente
9

Debes leer sobre cadenas pesadas. Un ejemplo de código está aquí.

<android.support.constraint.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:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <TextView
        android:id="@+id/figure_1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintEnd_toStartOf="@id/figure_2"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="1"
        />

    <TextView
        android:id="@+id/figure_2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintEnd_toStartOf="@id/figure_3"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@id/figure_1"
        tools:text="2"
        />

    <TextView
        android:id="@+id/figure_3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintEnd_toStartOf="@id/figure_4"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@id/figure_2"
        tools:text="3"
        />

    <TextView
        android:id="@+id/figure_4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@id/figure_3"
        tools:text="4"
        />
</android.support.constraint.ConstraintLayout>

Por lo tanto, establecer android:layout_width="0dp", app:layout_constraintHorizontal_weight="1"y vincular todas las vistas con los vecinos como:

app:layout_constraintStart_toEndOf="@id/figure_2"
app:layout_constraintEnd_toStartOf="@id/figure_4"

ingrese la descripción de la imagen aquí

CoolMind
fuente
¿Cuál es el punto de publicar una respuesta más exactamente como otra, publicada hace dos años?
@Subzero, vi muchas veces respuestas iguales con alta tasa. Incluso las líneas de código eran iguales. Sospecho que algunos autores copiaron los míos e incluso obtuvieron más ventajas. En este caso, las respuestas son diferentes, también utilicé otras fuentes para comprender cómo funcionan los pesos ConstraintLayout, y solo la primera respuesta no fue suficiente para obtener una imagen de arriba.
CoolMind
3

Una vez que tenga sus elementos encadenados, aún puede usar pesos en ellos como un diseño relativo para mantenerlos espaciados uniformemente. El siguiente ejemplo muestra cómo mantenerlos espaciados uniformemente con vistas de texto de diferentes tamaños.

<TextView1
     app:layout_constraintHorizontal_weight="1" />
 <TextView2
     app:layout_constraintHorizontal_weight="1" />
 <TextView3
     app:layout_constraintHorizontal_weight="1" />
 <TextView4
     app:layout_constraintHorizontal_weight="1" />

ingrese la descripción de la imagen aquí

tzg
fuente