Подтвердить что ты не робот

Как центрировать несколько видов вместе, используя 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?

4b9b3361

Ответ 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.

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