Пример использования Android ConstraintLayout в сложном UI

Перевод статьи на Медиуме о построении пользовательского интерфейса с помощью компонента разметки ConstraintLayout.


Создайте сложный и отзывчивый интерфейс для вашего приложения

 

Пример использования Android ConstraintLayout в сложном UI

ConstraintLayout был представлен для создания очень сложных и отзывчивых пользовательских интерфейсов приложений. Ранее я использовал RelativeLayout для создания сложных пользовательских интерфейсов, пока не наткнулся на этот интерфейс.

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

Есть три шага для завершения входа в систему.

  1. Mobile Number
  2. OTP
  3. Profile

В настоящее время пользователь находится на первом шаге, а именно «введите номер мобильного телефона».

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

Те, кто не знаком с ConstraintLayout, сначала должны прочитать документацию по Android ConstraintLayout.

Давайте начнем.

Внедрение ConstraintLayout в проект

Сначала добавьте зависимость Gradle в ваш проект.

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
}

Использование Guideline

Так выглядит пользовательский интерфейс, о котором пойдет речь ниже, в режиме конструктора в Android Studio.

Создание этого интерфейса стало возможным благодаря использованию Guideline.

Guideline — это аналог линии, устанавливаемой на макетах в визуальных редакторах, по которой дизайнеры выравнивают элементы. Такую линию представляет view класса android.support.constraint.Guideline. Guideline может быть горизонтальным или вертикальным — это указывается атрибутом android:orientation. Сам guideline нулевого размера, не занимает места в контейнере и всегда привязан только к сторонам ConstraintLayout.

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

После добавления Guideline , вот как выглядит 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="80dp"
    android:paddingBottom="8dp">
  
  <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />
<android.support.constraint.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />
</android.support.constraint.ConstraintLayout>

Строка app:layout_constraintGuide_percent=”0.5" определяет, где именно вы хотите установить Guideline. В моем случае я хотел, чтобы это было в центре, поэтому установил значение 0,5.

Если вы хотите добавить TextView горизонтально, например, точно на 3/4 ширины экрана, вам нужно добавить вертикальную направляющую. Это действительно было бы вертикальным ориентиром. Мы делим экран по горизонтали, поэтому будем использовать vertical guideline.

Это будет выглядеть следующим образом:

<android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.75" />

Надеюсь, что это дает вам представление о Guideline. Мы вернемся к исходной проблеме сейчас.

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

Добавление ImageView

Во-первых, мы добавим ImageView точно в центр Guideline. Вот код:

<ImageView
    android:id="@+id/ivotp"
    android:layout_width="16dp"
    android:layout_height="16dp"
    android:layout_marginTop="8dp"
    android:background="@drawable/otp_process_circle"
    app:layout_constraintBottom_toTopOf="@+id/guideline1"
    app:layout_constraintEnd_toStartOf="@+id/guideline"
    app:layout_constraintStart_toStartOf="@+id/guideline"
    app:layout_constraintTop_toTopOf="@+id/guideline1" />

Разместить ваш ImageView точно по центру относительно горизонтальной направляющей помогают следующие строки:

app:layout_constraintBottom_toTopOf="@+id/guideline1" app:layout_constraintTop_toTopOf="@+id/guideline1"

А разместить ImageView точно по центру относительно вертикальной направляющей помогают следующие строки:

app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintStart_toStartOf="@+id/guideline"

Теперь мы добавим разделители слева и справа от этого ImageView, как того требует пользовательский интерфейс:

<ImageView
    android:id="@+id/ivseconddiv"
    android:layout_width="76dp"
    android:layout_height="2dp"
    android:background="@drawable/stroke_divider"
    android:layerType="software"
    app:layout_constraintBottom_toBottomOf="@+id/ivotp"
    app:layout_constraintStart_toEndOf="@+id/ivotp"
    app:layout_constraintTop_toTopOf="@+id/ivotp" />
<ImageView
    android:id="@+id/ivfirstdiv"
    android:layout_width="76dp"
    android:layout_height="2dp"
    android:layerType="software"
    android:src="@drawable/stroke_divider"
    app:layout_constraintBottom_toBottomOf="@+id/ivotp"
    app:layout_constraintEnd_toStartOf="@+id/ivotp"
    app:layout_constraintTop_toTopOf="@+id/ivotp" />

Строки ниже помещают разделитель точно по центру по вертикали относительно ImageView ivotp:

app:layout_constraintBottom_toBottomOf

app:layout_constraintTop_toTopOf

Вот как выглядит наш пользовательский интерфейс:

В конце этих разделителей мы добавим два ImageViews, как показано ниже:

<ImageView
    android:id="@+id/ivnumberfill"
    android:layout_width="16dp"
    android:layout_height="16dp"
    app:layout_constraintBottom_toBottomOf="@+id/ivfirstdiv"
    app:layout_constraintEnd_toStartOf="@+id/ivfirstdiv"
    app:layout_constraintTop_toTopOf="@+id/ivfirstdiv"
    app:srcCompat="@drawable/ic_otp_fill" />
<ImageView
    android:id="@+id/ivprofile"
    android:layout_width="16dp"
    android:layout_height="16dp"
    android:layout_toRightOf="@+id/ivseconddiv"
    android:background="@drawable/otp_process_circle"
    app:layout_constraintBottom_toBottomOf="@+id/ivseconddiv"
    app:layout_constraintStart_toEndOf="@+id/ivseconddiv"
    app:layout_constraintTop_toTopOf="@+id/ivseconddiv" />

Вот как выглядит наш пользовательский интерфейс:

Теперь нам просто нужно добавить три TextView под каждым кругом ImageView, точно в центре по горизонтали. Вот код, чтобы добавить это:

<TextView
    android:id="@+id/tvnumber"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/ivnumberfill"
    android:layout_marginTop="4dp"
    android:text="Mobile Number"
    android:textColor="?colorAccent"
    android:textSize="11sp"
    app:layout_constraintEnd_toEndOf="@id/ivnumberfill"
    app:layout_constraintStart_toStartOf="@id/ivnumberfill"
    app:layout_constraintTop_toBottomOf="@id/ivnumberfill" />
<TextView
    android:id="@+id/tvotp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/ivnumberfill"
    android:layout_marginTop="8dp"
    android:text="OTP"
    android:textColor="#949595"
    android:textSize="11sp"
    app:layout_constraintEnd_toStartOf="@+id/ivseconddiv"
    app:layout_constraintStart_toStartOf="@+id/ivotp"
    app:layout_constraintTop_toBottomOf="@+id/ivotp" />
<TextView
    android:id="@+id/tvprofile"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/ivnumberfill"
    android:layout_marginTop="8dp"
    android:text="Profile"
    android:textColor="#949595"
    android:textSize="11sp"
    app:layout_constraintEnd_toEndOf="@+id/ivprofile"
    app:layout_constraintStart_toStartOf="@+id/ivprofile"
    app:layout_constraintTop_toBottomOf="@+id/ivprofile" />

В приведенном выше коде строки app: layout_constraintEnd_toEndOf и app: layout_constraintStart_toStartOf  выровняют текст по горизонтали относительно ImageView, а строка app: layout_constraintTop_toBottomOf  выровняет текст под ImageView.

Финальный результат и код

Вот наш пользовательский интерфейс и наш окончательный код XML:

<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="80dp"
    android:paddingBottom="8dp">
<ImageView
        android:id="@+id/ivotp"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_marginTop="8dp"
        android:background="@drawable/otp_process_circle"
        app:layout_constraintBottom_toTopOf="@+id/guideline1"
        app:layout_constraintEnd_toStartOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="@+id/guideline1" />
<ImageView
        android:id="@+id/ivseconddiv"
        android:layout_width="76dp"
        android:layout_height="2dp"
        android:background="@drawable/stroke_divider"
        android:layerType="software"
        app:layout_constraintBottom_toBottomOf="@+id/ivotp"
        app:layout_constraintStart_toEndOf="@+id/ivotp"
        app:layout_constraintTop_toTopOf="@+id/ivotp" />
<ImageView
        android:id="@+id/ivfirstdiv"
        android:layout_width="76dp"
        android:layout_height="2dp"
        android:layerType="software"
        android:src="@drawable/stroke_divider"
        app:layout_constraintBottom_toBottomOf="@+id/ivotp"
        app:layout_constraintEnd_toStartOf="@+id/ivotp"
        app:layout_constraintTop_toTopOf="@+id/ivotp" />
<ImageView
        android:id="@+id/ivnumberfill"
        android:layout_width="16dp"
        android:layout_height="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/ivfirstdiv"
        app:layout_constraintEnd_toStartOf="@+id/ivfirstdiv"
        app:layout_constraintTop_toTopOf="@+id/ivfirstdiv"
        app:srcCompat="@drawable/ic_otp_fill" />
<ImageView
        android:id="@+id/ivprofile"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_toRightOf="@+id/ivseconddiv"
        android:background="@drawable/otp_process_circle"
        app:layout_constraintBottom_toBottomOf="@+id/ivseconddiv"
        app:layout_constraintStart_toEndOf="@+id/ivseconddiv"
        app:layout_constraintTop_toTopOf="@+id/ivseconddiv" />
<TextView
        android:id="@+id/tvnumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ivnumberfill"
        android:layout_marginTop="4dp"
        android:text="Mobile Number"
        android:textColor="?colorAccent"
        android:textSize="11sp"
        app:layout_constraintEnd_toEndOf="@id/ivnumberfill"
        app:layout_constraintStart_toStartOf="@id/ivnumberfill"
        app:layout_constraintTop_toBottomOf="@id/ivnumberfill" />
<TextView
        android:id="@+id/tvotp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ivnumberfill"
        android:layout_marginTop="8dp"
        android:text="OTP"
        android:textColor="#949595"
        android:textSize="11sp"
        app:layout_constraintEnd_toStartOf="@+id/ivseconddiv"
        app:layout_constraintStart_toStartOf="@+id/ivotp"
        app:layout_constraintTop_toBottomOf="@+id/ivotp" />
<TextView
        android:id="@+id/tvprofile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ivnumberfill"
        android:layout_marginTop="8dp"
        android:text="Profile"
        android:textColor="#949595"
        android:textSize="11sp"
        app:layout_constraintEnd_toEndOf="@+id/ivprofile"
        app:layout_constraintStart_toStartOf="@+id/ivprofile"
        app:layout_constraintTop_toBottomOf="@+id/ivprofile" />
<android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />
<android.support.constraint.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />
</android.support.constraint.ConstraintLayout>

После создания этого интерфейса я понимаю важность использования ConstraintLayout. Теперь я стараюсь использовать ConstraintLayout везде, где это возможно.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий