Создайте вертикальную цепочку из нескольких горизонтальных цепочек с плоской иерархией представления ConstraintLayout

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

Исходный макет

<?xml version="1.0" encoding="utf-8"?>
<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="match_parent">

    <Button
        android:id="@+id/btnTopLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#eeeeee"
        app:layout_constraintBottom_toTopOf="@+id/lblTopLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnTopRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="1"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblTopLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toTopOf="@+id/btnMiddleLeft"
        app:layout_constraintEnd_toEndOf="@id/btnTopLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnTopLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnTopLeft"
        tools:text="Button 1" />

    <Button
        android:id="@+id/btnTopRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#dddddd"
        app:layout_constraintBottom_toTopOf="@+id/lblTopRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnTopLeft"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="2"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblTopRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toTopOf="@+id/btnMiddleRight"
        app:layout_constraintEnd_toEndOf="@id/btnTopRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnTopRight"
        app:layout_constraintTop_toBottomOf="@+id/btnTopRight"
        tools:text="Button 2" />

    <Button
        android:id="@+id/btnMiddleLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#cccccc"
        app:layout_constraintBottom_toTopOf="@+id/lblMiddleLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnMiddleRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/lblTopLeft"
        tools:text="3"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblMiddleLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toTopOf="@+id/btnBottomLeft"
        app:layout_constraintEnd_toEndOf="@id/btnMiddleLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnMiddleLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnMiddleLeft"
        tools:text="Button 3" />

    <Button
        android:id="@+id/btnMiddleRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#bbbbbb"
        app:layout_constraintBottom_toTopOf="@+id/lblMiddleRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnMiddleLeft"
        app:layout_constraintTop_toBottomOf="@+id/lblTopRight"
        tools:text="4"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblMiddleRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toTopOf="@+id/btnBottomRight"
        app:layout_constraintEnd_toEndOf="@id/btnMiddleRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnMiddleRight"
        app:layout_constraintTop_toBottomOf="@+id/btnMiddleRight"
        tools:text="Button 4" />

    <Button
        android:id="@+id/btnBottomLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#aaaaaa"
        app:layout_constraintBottom_toTopOf="@+id/lblBottomLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnBottomRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/lblMiddleLeft"
        tools:text="5"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblBottomLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@id/btnBottomLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnBottomLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnBottomLeft"
        tools:text="Button 5" />

    <Button
        android:id="@+id/btnBottomRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#999999"
        app:layout_constraintBottom_toTopOf="@+id/lblBottomRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnBottomLeft"
        app:layout_constraintTop_toBottomOf="@+id/lblMiddleRight"
        tools:text="6"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblBottomRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@id/btnBottomRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnBottomRight"
        app:layout_constraintTop_toBottomOf="@+id/btnBottomRight"
        tools:text="Button 6" />

</android.support.constraint.ConstraintLayout>

Когда я устанавливаю видимость кнопки и ее TextView, я хочу, чтобы кнопка в той же строке заполняла оставшееся пространство, но я хочу, чтобы кнопки под ней или над ней оставались на том же месте, пока оба кнопки в строке были скрыты. После того, как обе кнопки в одной строке были скрыты, я хотел бы, чтобы оставшиеся кнопки заполнили оставшееся пространство. Например, вот как я хочу, чтобы макет выглядел, когда я скрываю Button и TextView 3:

Правильный макет

Но в настоящее время, если я скрою Button и TextView 3, вот что сейчас произойдет:

Неверный макет

Это ожидаемое поведение, основанное на моем текущем коде, но я ищу способ предотвратить схлопывание вертикальной цепочки до тех пор, пока кнопка 4 также не будет скрыта. Когда кнопка 4 скрыта, это желаемый результат:

Правильный макет 2

Я поиграл с барьерами, но размещение барьера в любой точке, кажется, вызывает сложности с динамической высотой кнопок, потому что это разрывает вертикальную цепочку. Может ли кто-нибудь дать некоторое представление о том, как добиться этого с помощью иерархии плоского представления?


person David    schedule 20.05.2019    source источник


Ответы (1)


Разделите экран на три вертикально связанных представления следующим образом:

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

Я установил цвета фона, чтобы сделать представления более заметными, но в реальной реализации они, вероятно, будут прозрачными или заданы как невидимые.

Теперь добавьте кнопки и метки, чтобы они были вертикально ограничены внутренней частью этих представлений. Это нарушает вертикальные цепочки, но вертикальный размер теперь контролируется вертикальными цепочками базовых представлений. Кнопки и метки по-прежнему привязаны к сторонам ConstraintLayout.

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

Кнопки и метки по-прежнему изменяются влево и вправо, как и раньше. Однако теперь кнопка внизу не будет расширяться до тех пор, пока для всех представлений подряд не будет установлено значение «исчезло».

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

Вам нужно будет установить базовый вид на «ушел», когда все кнопки и метки в строке также установлены на «ушли», поэтому вам нужно будет отслеживать статус кнопок и меток в строке.

Вот XML:

activity_main.xml

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

    <View
        android:id="@+id/topGroup"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintBottom_toTopOf="@id/centerGroup"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/centerGroup"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_blue_light"
        app:layout_constraintBottom_toTopOf="@id/bottomGroup"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/topGroup" />

    <View
        android:id="@+id/bottomGroup"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_orange_light"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/centerGroup" />

    <Button
        android:id="@+id/btnTopLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#eeeeee"
        app:layout_constraintBottom_toTopOf="@+id/lblTopLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnTopRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/topGroup"
        tools:text="1"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblTopLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@+id/topGroup"
        app:layout_constraintEnd_toEndOf="@id/btnTopLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnTopLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnTopLeft"
        tools:text="Button 1" />

    <Button
        android:id="@+id/btnTopRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#dddddd"
        app:layout_constraintBottom_toTopOf="@+id/lblTopRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnTopLeft"
        app:layout_constraintTop_toTopOf="@id/topGroup"
        tools:text="2"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblTopRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@+id/topGroup"
        app:layout_constraintEnd_toEndOf="@id/btnTopRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnTopRight"
        app:layout_constraintTop_toBottomOf="@+id/btnTopRight"
        tools:text="Button 2" />

    <Button
        android:id="@+id/btnMiddleLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#cccccc"
        app:layout_constraintBottom_toTopOf="@+id/lblMiddleLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnMiddleRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/centerGroup"
        tools:text="3"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblMiddleLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@+id/centerGroup"
        app:layout_constraintEnd_toEndOf="@id/btnMiddleLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnMiddleLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnMiddleLeft"
        tools:text="Button 3" />

    <Button
        android:id="@+id/btnMiddleRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#bbbbbb"
        app:layout_constraintBottom_toTopOf="@+id/lblMiddleRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnMiddleLeft"
        app:layout_constraintTop_toTopOf="@+id/centerGroup"
        tools:text="4"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblMiddleRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@+id/centerGroup"
        app:layout_constraintEnd_toEndOf="@id/btnMiddleRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnMiddleRight"
        app:layout_constraintTop_toBottomOf="@+id/btnMiddleRight"
        tools:text="Button 4" />

    <Button
        android:id="@+id/btnBottomLeft"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#aaaaaa"
        app:layout_constraintBottom_toTopOf="@+id/lblBottomLeft"
        app:layout_constraintEnd_toStartOf="@+id/btnBottomRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/bottomGroup"
        tools:text="5"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblBottomLeft"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@id/bottomGroup"
        app:layout_constraintEnd_toEndOf="@id/btnBottomLeft"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnBottomLeft"
        app:layout_constraintTop_toBottomOf="@+id/btnBottomLeft"
        tools:text="Button 5" />

    <Button
        android:id="@+id/btnBottomRight"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#999999"
        app:layout_constraintBottom_toTopOf="@+id/lblBottomRight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnBottomLeft"
        app:layout_constraintTop_toTopOf="@+id/bottomGroup"
        tools:text="6"
        tools:textSize="42sp" />

    <TextView
        android:id="@+id/lblBottomRight"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="@id/bottomGroup"
        app:layout_constraintEnd_toEndOf="@id/btnBottomRight"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@id/btnBottomRight"
        app:layout_constraintTop_toBottomOf="@+id/btnBottomRight"
        tools:text="Button 6" />

</android.support.constraint.ConstraintLayout>
person Cheticamp    schedule 21.05.2019
comment
Я на самом деле думал об этом, но это казалось немного хакерским. Я надеялся, что в ConstraintLayout есть лучший способ сделать это, чем необходимость управлять базовыми невидимыми представлениями и количеством видимых кнопок в каждой строке, но, возможно, ConstraintLayout еще не совсем готов. Я отмечу это как ответ, если более элегантное решение не будет опубликовано в течение дня или двух. - person David; 21.05.2019
comment
@David Барьеры кажутся ответом, но они плохо сочетаются с цепями. В ConstraintLayout 2.0 есть несколько новых возможностей, таких как линейный помощник, который может здесь пригодиться. К сожалению, на сегодняшний день существует мало документации по этим функциям. - person Cheticamp; 21.05.2019
comment
Я собираюсь пойти дальше и принять ваш ответ как правильный. Я продолжаю обнаруживать, что если я хочу сделать какой-либо дизайн, выходящий за рамки основ, мне нужно создать невидимое представление и настроить ограничения, как если бы представление было контейнером для его подпредставлений (т. е. предоставленное вами решение). Моя иерархия представлений остается плоской, но ее гораздо сложнее понять. Я немного разочарован тем, что ConstraintLayout недостаточно мощен, чтобы лучше справляться с этими сценариями, но я уверен, что со временем он станет более надежным. - person David; 21.05.2019