Как совместить несколько видов с помощью ConstraintLayout?

Фон

Google анонсировал новый макет под названием «ConstraintLayout«Это должен быть окончательный макет, который может заменить все макеты, оставаясь плоским (без вложенных макетов) и иметь лучшую производительность.

Эта проблема

Дело в том, что я едва вижу какие-либо учебники для него, которые могли бы помочь мне в этом вопросе, кроме видео, представленного в Google IO.

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

В конце концов, это цель этого нового макета ...

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

Обратите внимание, что представления в центре расположены только по центру по вертикали, и что 2 текстовых вида расположены справа от ImageView, который также центрирован по вертикали.

Все это хорошо работает с RelativeLayout, который имеет LinearLayout из 2 TextView, но я хотел бы знать, как преобразовать их в один ConstraintLayout.

Вот пример XML того, что я показал:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    android:minHeight="?attr/listPreferredItemHeightSmall">

    <ImageView
        android:id="@+id/appIconImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="4dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="4dp"
        android:layout_marginStart="2dp"
        android:adjustViewBounds="true"
        android:src="@android:drawable/sym_def_app_icon"
        tools:ignore="ContentDescription"/>

    <LinearLayout
        android:id="@+id/appDetailsContainer"
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/appIconImageView"
        android:layout_toLeftOf="@+id/overflowView"
        android:layout_toRightOf="@+id/appIconImageView"
        android:layout_toStartOf="@+id/overflowView"
        android:orientation="vertical">

        <TextView
            android:id="@+id/appLabelTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:text="label"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>

        <TextView
            android:id="@+id/appDescriptionTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:minLines="3"
            android:text="description"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/overflowView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:adjustViewBounds="true"
        android:background="?attr/selectableItemBackground"
        android:clickable="true"
        android:padding="10dp"
        app:srcCompat="@drawable/ic_more_vert_black_24dp"

        tools:src="@drawable/ic_more_vert_black_24dp"
        tools:ignore="ContentDescription"/>

    <ImageView
        android:id="@+id/isSystemAppImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/overflowView"
        android:layout_alignLeft="@+id/overflowView"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/overflowView"
        android:layout_alignStart="@+id/overflowView"
        android:adjustViewBounds="true"
        android:scaleType="centerInside"
        app:srcCompat="@drawable/ic_warning_black_24dp"
        tools:ignore="ContentDescription"
        tools:src="@drawable/ic_warning_black_24dp"/>

</RelativeLayout>
Что я пробовал

Я попытался прочитать несколько статей и посмотреть видео Google:

https://codelabs.developers.google.com/codelabs/constraint-layout/index.html#0https://www.youtube.com/watch?v=sO9aX87hq9chttps://youtu.be/csaXml4xtN8?t=1693

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

Вопрос

Как я могу преобразовать 2 макета в один ConstraintLayout?

 pskink29 мая 2016 г., 09:48
 android developer04 июн. 2016 г., 09:12
@DevrimTuncer Да. и результат не сгладил это вообще. Вы можете увидеть мою попытку здесь:code.google.com/p/android/issues/detail?id=212116
 android developer29 мая 2016 г., 11:41
@pskink Вроде, но центрированные виды имеют 2 текстовых вида, один под другим. Не один. В настоящее время они находятся внутри LinearLayout, который центрирован. Кроме того, LinearLayout находится между правым и левым видами.
 Devrim04 июн. 2016 г., 00:08
Вы пробовали автоматическое преобразование на панели дизайна? "Конвертировать <your_layout> в ConstraintLayout"?

Ответы на вопрос(5)

Центрирующие компоненты в ConstraintLayout)

А пока вы можете центрировать «изображение» (ограничивать слева-сверху-снизу), ограничивать «метку» сверху до «изображения» вверху, ограничивать «описание» сверху вниз до «метки» снизу. В приведенном ниже примере я сопоставил высоту кнопки с двумя текстовыми изображениями справа (это ваш случай). Другие текстовые представления ограничены как на ссылке выше.

ОБНОВЛЕНИЕ: Отвечая на ваш комментарий ниже:

Я установил ваше приложение, и это только я могу думать в настоящее время. Поскольку это макет ViewHolder, layout_height может быть установлен на wrap_content, или вы можете исправить это, если хотите. Я могу отправить вам XML, если вы хотите, я не хочу, чтобы получить ответ.

Верхнее левое ограничение TextView ограничено правым ограничением ImageView. Кроме того, ограничение сверху TextView -> top ограничено вершиной контейнера, поэтому верно. Дно TextView ограничено дном контейнера. TextViews в середине ограничены шириной верхнего TextView и не имеют связи с ImageView.

 android developer09 июн. 2016 г., 12:49
Я спросил о центрировании 2 просмотров (вместе). Не один.
 android developer09 июн. 2016 г., 15:42
Я попробую, когда у меня будет время. Как я заметил, только недавно они исправили ошибку, которая не позволяет использовать новый макет в RecyclerView.
 bajicdusko09 июн. 2016 г., 12:51
@androiddeveloper Да, я в курсе, я предложил обходной путь. Это визуально выглядит так же. Проблема по-прежнему остается, конечно, так как мы оба хотим центрировать несколько компонентов, взаимно ограниченных.
 android developer09 июн. 2016 г., 13:12
На самом деле, возможно, это может быть хорошим решением в моем случае. Макет, который я использую, предназначен для элементов в RecyclerView (в этом приложении:play.google.com/store/apps/details?id=com.lb.app_manager ) Возможно, я мог бы установить верхний TextView, чтобы он занимал верхнюю часть (но с гравитационным дном), а нижний TextView - для нижней (под верхним TextView). Как вы думаете, это может выглядеть так же?
 bajicdusko09 июн. 2016 г., 15:28
@androiddeveloper Я обновил свой ответ с макетом, характерным для вашего приложения. Надеюсь, это может помочь.

app:layout_constraintVertical_bias="0.5" для видов, которые должны быть центрированы по вертикали, атрибут смещения работает, только если вы указываете ограничения для границ (например, верх и низ для вертикального смещения, левый и правый для горизонтального смещения)

Пример:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraintLayout">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@id/constraintLayout"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintVertical_bias="0.5" />

</android.support.constraint.ConstraintLayout>

Получил это работает в моем макете здесь:https://github.com/hidroh/tldroid/blob/master/app/src/main/res/layout/activity_main.xml, очень похожий макет, хотя я размещаю вещи на 1/3 высоты экрана.

 hidro31 мая 2016 г., 02:31
Вы смотрели файл Github в моем ответе? Это почти идентично, просто измените значение смещения в моем макете на 0,5 вместо 0,3.
 hidro30 мая 2016 г., 15:05
Мой макет имеет 2 TextViews. Я приведу только пример того, как центрировать представление 1 по вертикали внутри ConstraintLayout. Если вы хотите связать их, установите атрибут смещения для каждого из них. В моем случае я установил только 1 TextView и использую его в качестве привязки для другого.
 android developer30 мая 2016 г., 22:21
Не могли бы вы показать, как это сделать для случая, который я представил? один TextView над другим, в то время как оба вместе, по центру?
 android developer30 мая 2016 г., 15:01
Я не понимаю У меня есть 2 TextViews. Я мог бы иметь больше. Я хочу, чтобы они были центрированы вертикально. Что я должен делать?
Решение Вопроса
Посмотрите на мой ответВот.

ContraintLayout содержит функцию -Chains - это позволяет реализовать то, что вы просите:

Цепочки обеспечивают групповое поведение на одной оси (по горизонтали или по вертикали).

Набор виджетов считается цепочкой, если они связаны между собой через двунаправленное соединение

После создания цепочки есть две возможности:

Распределите элементы в доступном пространствеЦепочка также может быть «упакована», в этом случае элементы сгруппированы вместе

Что касается вашего случая, вам придется упаковатьlabel а такжеdescription TextViews и центрируйте их в родительском элементе вертикально:

(убедитесь, что вы используете версию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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainPacked="true"/>

    <TextView
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button\nMkay"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toBottomOf="@+id/textView"/>

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>
</android.support.constraint.ConstraintLayout>
 android developer18 окт. 2016 г., 13:31
Я имею в виду, как он узнает, какие взгляды объединить. В LinearLayout все виды находятся внутри него.
 android developer22 янв. 2019 г., 13:38
@YuryFedorov Спасибо за все объяснения.
 android developer18 окт. 2016 г., 12:56
Как оно группирует взгляды?
 mbonnin18 апр. 2017 г., 09:33
@Yury Согласен, я немного отредактировал ответ, чтобы сделать его более четким. Как только смогу, уберу внизу
 Saeid Z24 июн. 2019 г., 15:54
@ Юрий Федоров Спасибо. Теперь в компоновке ограничений 1.1.3 мы должны использовать app: layout_constraintHorizont_chainStyle = "pack" вместо app: layout_constraintVertical_chainPacked = "true"
 Yury Fedorov18 апр. 2017 г., 08:52
@mbonnin Вопрос был именно в том, как центрировать взгляды в родителе, а не выровнять относительно друг друга. Я думаю, что недооценка ответа, который не отвечает на ваш вопрос, но отвечает на вопрос ОП, неуместна.
 Yury Fedorov18 окт. 2016 г., 13:34
Определение цепочки: «Набор виджетов считается цепочкой, если они связаны друг с другом через двунаправленное соединение» - в этом примере два представления зависят друг от друга (textView находится над кнопкой, а кнопка - ниже textView), поэтому они называются цепочкой и группируются вместе. Пожалуйста, перейдите по ссылкам и найдите больше информации об этом.
 android developer18 окт. 2016 г., 20:32
Но есть несколько взглядов, которые зависят друг от друга. Как он узнает, кто должен быть в какой группе цепи?
 Yury Fedorov18 окт. 2016 г., 13:02
Он использует новую функцию ConstraintLayout - цепочки. Проверьте мой другой ответ с дополнительной информацией и ссылками на него
 mbonnin17 апр. 2017 г., 18:19
Это работает, только если вы отцентрируете метку и изображение дроида в родительском. Вы не можете выровнять их вертикально один относительно другого. Смотрите ответ @Marcin вместо этого.
 Yury Fedorov18 окт. 2016 г., 20:54
Я не знаю деталей реализации. Что я знаю, так это то, что представления, которые ссылаются друг на друга в своих ограничениях, образуют цепочку, и ее поведение определяется ее первым членом.

Этот ответ был написан до того, как стали доступны цепи. Пожалуйста, используйте цепочки сейчас, см. Ответ выше:https://stackoverflow.com/a/40102296/1402641

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

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

Они упоминают это вих разговор ввода / вывода (связано с точным временем). Так что, думаю, следите за обновлениями.

 android developer03 июн. 2016 г., 21:59
Откуда ты все это знаешь? Я не помню, чтобы слышал об этом в лекции Google IO, а также ни в одной статье.
 Marcin Koziński03 июн. 2016 г., 21:41
Виртуальных групп еще не существует. Это концепция, что команда позадиConstraintLayout хочу представить. Они решили выпустить рано, без всех функций и без обработки всех распространенных случаев.
 Marcin Koziński03 июн. 2016 г., 13:08
Да, дело в том, чтобы сгладить. Ваш сценарий не особенный, просто еще не обработан. Это просто по версииalpha2, Виртуальные группы приходят, чтобы справиться с вашим сценарием.
 android developer04 июн. 2016 г., 09:14
Странный. Я тоже смотрел это. Вероятно, пропустил эту часть или думал, что она уже доступна. Благодарю. Поскольку это еще не доступно, кажется, я добавлю только +1 к вашему сообщению и комментариям. Как только вы сможете получить рабочее решение для этого (используя новые «виртуальные группы»), я приму этот ответ
 android developer03 июн. 2016 г., 21:38
Как вы используете "виртуальные группы"? Есть ли какой-нибудь пример этого? Я не думаю, что видел это.
 android developer03 июн. 2016 г., 12:12
Но у RelativeLayout уже есть LinearLayout внутри. Разве нет смысла сводить все это к единому макету? Мой сценарий такой особенный?
 Marcin Koziński03 июн. 2016 г., 22:33
На самом деле мне удалось найти в разговоре о вводе / выводе :) Но они назвали его «виртуальными контейнерами», поэтому я отредактирую свой ответ и опубликую ссылку.

противоположное ограничение на макете.

По центру вертикально

    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"

По центру горизонтально

    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
 Ego Slayer19 июл. 2017 г., 10:12
Спасибо, просто и понятно.
 Abu Mohammad Rasel14 мар. 2019 г., 08:08
это единственный центр один вид
 ankit suthar14 июл. 2017 г., 06:55
Пожалуйста, посмотрите это первымкак к ответу  Ответ на этот вопрос раньше, очевидно, вы можете добавить свой ответ здесь. Но вам нужно понять некоторые моменты, прежде чем ответить. Во-первых, не добавляйте ответ, который ранее был добавлен с тем же кодом или предложением. Во-вторых, не добавляйте слишком сложный ответ, если пользователь задал очень конкретный вопрос о проблеме и что ему нужно для ее решения. В-третьих, вы можете добавить комментарий, если хотите что-то предложить относительно ответа или вопроса.

Ваш ответ на вопрос