Как центрировать несколько видов вместе, используя ConstraintLayout?
Фон
Google объявил о новом макете под названием " ConstraintLayout ", который должен быть окончательным макетом, который может заменить все макеты, оставаясь плоским (без вложенных макетов), и иметь лучшую производительность.
Эта проблема
Дело в том, что я едва вижу какие-либо учебники для него, которые могли бы помочь мне в этом вопросе, кроме видео, представленного в Google IO.
То, что я пытаюсь сделать, это, учитывая, что у меня есть LinearLayout с вертикальным центром в другом макете - преобразовать их оба в один ConstraintLayout.
В конце концов, это цель этого нового макета...
Макет, с которым я хочу иметь дело, выглядит следующим образом:
![enter image description here]()
Обратите внимание, что представления в центре расположены только по центру по вертикали, и что 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:
Это не помогло, поэтому я попытался использовать его, надеясь, что сам найду способ его использовать. Но я не могу понять, как это сделать. Я попытался использовать эту функцию для преобразования макетов, но это создает огромный беспорядок в представлениях и добавляет дополнительные поля, которые я не хочу иметь.
Вопрос
Как я могу преобразовать 2 макета в один ConstraintLayout?
Ответы
Ответ 1
Посмотрите на мой ответ здесь.
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_constraintHorizontal_chainStyle="packed"/>
<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>
Обновление 25-06-2019 (@Saeid Z):
Теперь в компоновке ограничений 1.1.3 мы должны использовать app:layout_constraintHorizontal_chainStyle="packed"
вместо app:layout_constraintVertical_chainPacked="true"
Ответ 2
Чтобы центрировать что-то вертикально или горизонтально, установите противоположное ограничение на макет.
Центрирование по вертикали
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
По центру горизонтально
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
Ответ 3
Установите 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 высоты экрана.
![введите описание изображения здесь]()
Ответ 4
EDIT: этот ответ был написан до того, как стали доступны цепочки. Теперь используйте цепочки, см. Выше ответ: fooobar.com/questions/295720/...
На данный момент я считаю, что ваш единственный выбор состоит в том, чтобы обернуть два текстовых представления в другом макете - возможно, линейная компоновка лучше всего подходит для этой ситуации.
Но команда за компоновкой ограничений заявила, что хочет ввести "виртуальные контейнеры", которые служат именно в этом случае: вы группируете два или более вида вместе и устанавливаете ограничение (например, центрирование по вертикали) на контейнере. Идея состоит в том, что это не полный вложенный макет внутри макета ограничения, а просто то, что использует макет ограничения, чтобы разместить его дочерние элементы - следовательно, он должен обеспечивать лучшую производительность, чем вложенность.
Они упоминают это в о своих разговорах о вводе/выводе (связанных с точным временем). Поэтому я думаю, оставайтесь с нами.
Ответ 5
Взгляните на мой пример (Центральные компоненты в ConstraintLayout)
Теперь вы можете центрировать "изображение" (ограничивать левое верхнее дно), сдерживать "ярлык" сверху до "изображения" сверху, сдерживать "описание" сверху до "метки" снизу.
В приведенном ниже примере я подобрал высоту кнопки с двумя текстовыми изображениями справа (это ваш случай). Другие текстовые сообщения ограничены по ссылке выше.
![введите описание изображения здесь]()
UPDATE: ответ на ваш комментарий ниже:
Я установил ваше приложение, и об этом я могу только сейчас подумать. Поскольку это макет ViewHolder, layout_height может быть установлен в wrap_content, или вы можете исправить его, если хотите. Я могу отправить вам xml, если хотите, я не хочу наводнять ответ.
Ограничение верхнего текста TextView ограничено правым ограничением ImageView. Кроме того, верхнее ограничение TextView → top ограничено вершиной контейнера, так что это правильно. Нижний TextView ограничен дном контейнера. TextViews в середине ограничены шириной верхнего TextView и не связаны с ImageView.
![введите описание изображения здесь]()