Равномерное представление с использованием ConstraintLayout


174

Обычно используется для LinearLayoutравномерного распределения (веса) представлений, например: пример макета

Как вы реализуете равномерно расположенные виды, как это, используя новый ConstraintLayout?

ConstraintLayoutссылки для справки: запись в блоге , видео сеанса ввода / вывода

Ответы:


323

Есть два способа сделать это, используя ConstraintLayout: Цепочки и Рекомендации . Чтобы использовать цепочки, убедитесь, что вы используете ConstraintLayoutбета-версию 3 или новее, и если вы хотите использовать редактор визуального макета в Android Studio, убедитесь, что вы используете Android Studio 2.3 бета-версию 1 или новее.

Метод 1 - Использование цепочек

Откройте редактор макетов и добавьте виджеты как обычно, добавив родительские ограничения по мере необходимости. В этом случае я добавил две кнопки с ограничениями в нижней части родителя и на стороне родителя (левая сторона для кнопки «Сохранить» и правая сторона для кнопки «Поделиться»):

введите описание изображения здесь

Обратите внимание, что в этом состоянии, если я переключу на альбомный вид, представления не заполняют родительский, а привязываются к углам:

введите описание изображения здесь

Выделите оба вида, нажав Ctrl / Cmd или перетащив рамку вокруг видов:

введите описание изображения здесь

Затем щелкните правой кнопкой мыши на видах и выберите «Центр по горизонтали»:

введите описание изображения здесь

Это устанавливает двунаправленную связь между представлениями (так определяется цепочка). По умолчанию стиль цепочки является «распространенным», который применяется, даже если атрибут XML не включен. Придерживаясь этого стиля цепочки, но устанавливая ширину наших представлений, чтобы 0dpпредставления заполняли доступное пространство, равномерно распределяясь по родительскому элементу:

введите описание изображения здесь

Это более заметно в альбомной ориентации:

введите описание изображения здесь

Если вы предпочитаете пропустить редактор макетов, результирующий XML будет выглядеть так:

<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>

Подробности:

  • установка ширины каждого элемента 0dpили MATCH_CONSTRAINTпозволяет представлениям заполнять родительский элемент (необязательно)
  • виды должны быть связаны двунаправленно (справа от ссылки кнопки «Сохранить» для кнопки «Поделиться», слева от ссылки кнопки «Поделиться» для кнопки «Сохранить»), это будет происходить автоматически через редактор макетов при выборе «Центрировать по горизонтали»
  • первое представление в цепочке может указывать стиль цепочки через layout_constraintHorizontal_chainStyle, см. документацию для различных стилей цепочки, если стиль цепочки опущен, по умолчанию используется «распространение»
  • Вес цепи можно отрегулировать с помощью layout_constraintHorizontal_weight
  • этот пример для горизонтальной цепочки, есть соответствующие атрибуты для вертикальной цепочки

Метод 2 - Использование руководства

Откройте свой макет в редакторе и нажмите кнопку направляющей:

введите описание изображения здесь

Затем выберите «Добавить вертикальную направляющую»: введите описание изображения здесь

Появится новое руководство, которое по умолчанию, скорее всего, будет привязано к левому краю в относительных значениях (обозначено левой стрелкой):

относительное руководство редактора макетов

Нажмите стрелку влево, чтобы переключить ее на процентное значение, затем перетащите направляющую до отметки 50%:

руководство по редактору макетов

Теперь руководство можно использовать в качестве привязки для других видов. В моем примере я прикрепил правую кнопку сохранения и левую кнопку общего доступа к направляющей:

окончательный макет

Если вы хотите, чтобы представления заполняли доступное пространство, тогда ограничение должно быть установлено на «Любой размер» (волнистые линии, идущие горизонтально):

любое ограничение размера

(Это то же самое , как установка layout_widthTo 0dp).

Руководство также может быть легко создано в XML, а не с помощью редактора макетов:

<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" />

1
Я не мог найти способ, как создать руководство с ограничением. Я хочу, чтобы горизонтальная направляющая была посередине двух видов. Представьте себе более крупный вид с высотой 100dp сверху и меньший с высотой 50dp снизу. Я хочу разместить ориентир в середине пространства между ними.
Headsvk

3
Я не думаю, что вы можете добавить ограничения в само руководство. Вы можете добавить несколько рекомендаций, а затем ограничить представления этими рекомендациями. Возможно, вы захотите опубликовать новый вопрос с подробной информацией о том, чего вы пытаетесь достичь. Не стесняйтесь вставить его сюда.
AdamK

Спасибо, дорогой сэр. Это была своевременная и эффективная помощь.
iSofia,

Я хочу дать пропорциональную ширину видам. Например, я хочу, чтобы кнопка «Поделиться» имела двойную ширину кнопки сохранения. Без использования руководящих принципов, так как мои взгляды не расположены рядом друг с другом, как в этом примере. Является ли это возможным?
Шубхам Найк

Вы должны преобразовать значения, указанные в рекомендациях, в фактические поля или отступы. Руководства работают только в режиме проектирования.
Абхинав Саксена

49

Чтобы создать 2 вида в одну линию, равную ширину, просто нужно определить

<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>

Заметка

  • ширина = 0 дп ( MATCH_CONSTRAINT)
  • Ограничение button1и button2должно нравиться выше

результат

БОЛЬШЕ
Если вы хотите View1больше, чем View2вы можете использовать weightили percent.
Например, View1ширина = 2 * View2ширина использовать вес

<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>

результат

Пример: View1ширина = 2 * View2ширина в процентах

<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>

результат


23

Ну если кому то поможет

ключ здесь app:layout_constraintHorizontal_weight="1"и
лучше всего об ограничении компоновки является то , что он поддерживает циклическую зависимость и вот это то , что я сделал , используя именно это.

Для первого ребенка
app:layout_constraintEnd_toStartOf="@+id/textInputSecondChild"

Для второго ребенка

app:layout_constraintLeft_toRightOf="@+id/textInputFirstChild"

вот полная демонстрация

<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>

9

Вы должны прочитать о взвешенных цепях. Пример кода здесь.

<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>

Таким образом, установить android:layout_width="0dp", app:layout_constraintHorizontal_weight="1"и связать каждый вид с соседями , как:

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

введите описание изображения здесь


какой смысл публиковать еще один ответ точно так же, как другой, опубликованный два года назад?

@ Subzero, я видел много раз равных ответов с высокой скоростью. Даже строки кода были одинаковыми. Подозреваю, некоторые авторы скопировали с моего и даже получили больше плюсов. В этом случае ответы разные, я также использовал другие источники, чтобы понять, как работают веса ConstraintLayout, и только первого ответа было недостаточно, чтобы получить картину выше.
CoolMind

3

После того, как у вас есть связанные элементы, вы все равно можете использовать их веса, например относительную компоновку, чтобы они оставались равномерно распределенными. В приведенном ниже примере показано, как сохранить их равномерно расположенными с различными размерами textViews

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

введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.