Activity и View. FrameLayout.

Урок #4

Урок 4 — Activity и View. FrameLayout.

Два самых важных элемента интерфейса Android приложения — это Activity и View.

View — это практически любой элемент интерфейса. Кнопка, поле для ввода текста, элемент, отображающий текст, и многое другое — это все разновидности View.

Activity — это совокупность View на одном экране. По сути, Activity — это экран приложения.

Также давайте познакомимся с понятием ViewGroup.

Если View — это просто элемент интерфейса, то ViewGroup — это View, который может содержать внутри другие View, то есть контейнер.

Layout

Layout — это категория ViewGroup, созданная для того, чтобы мы могли располагать элементы интерфейса так, как нам это нужно.

Самые популярные виды Layout:

  • LinearLayout
  • RelativeLayout
  • FrameLayout

На самом деле их намного больше, но большинство задач можно решить, используя эти три вида.

Все еще непонятно, что такое Layout? Посмотрите на эту картинку:

Layout в Android
Layout в Android

Кнопки и поле "Search" — это View. Зеленой рамочкой вокруг кнопок обозначены границы Layout (т.е. ViewGroup), внутри которого они находятся. А этот Layout и поле "Search", в свою очередь, находятся внутри другого Layout, границы которого обозначены красным цветом.

А весь белый фон — это Activity, экран, в котором располагаются остальные элементы интерфейса.

Создание интерфейса

Основной подход при разработке интерфейса — декларативный. Это значит, что вы создаете интерфейс не в Java-коде, а описываете его в специальных XML-файлах. Почти как верстка HTML :)

Помните, в прошлом уроке мы с вами говорили о ресурсах приложения? Так вот, верстка экранов — один из типов ресурсов. Файлы верстки находятся в директории res/layout.

Взгляните, в новом проекте уже есть один файл!

Лэйаут Activity
Лэйаут Activity

Этот файл описывает интерфейс нашей единственной Activity.

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

  • activity_name.xml — для вёрстки Activity.
  • fragment_name.xml — для вёрстки Fragment (о них поговорим в одном из следующих уроков).
  • view_name.xml — для вёрстки View.

Здесь "name" — имя элемента интерфейса. То есть файл для Activity с названием MainActivity должен называться activity_main.xml, а для PostsActivityactivity_posts.xml.

Итак, вернемся к нашему activity_main.xml.

Если вы откроете этот файл, то увидите визуальный редактор. На самом деле, намного удобнее и надежнее работать с XML-кодом, нежели с редактором. Внизу вы увидите две вкладки — Design и Text. Переключитесь на Text.

Переключение на редактирование XML
Переключение на редактирование XML

Вероятнее всего, вы увидите вот такой код:

<?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"
    tools:context="com.test.lessons.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Это ConstraintLayout. Мы обязательно поработаем с ним позже, но пока что он слишком сложен. Замените код на такой:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.lessons.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Hello World!" />

</FrameLayout>

Запустите приложение. Как видите, визуально ничего не поменялось.

Давайте же разберем, что тут написано.

Корневой элемент — FrameLayout. Это самый простой из возможных Layout-ов.

Внутри него находится TextView — это View, задачей которого является отображение текста. Получается, FrameLayout является контейнером для TextView.

Чтобы было понятнее, покажу структуру, отбросив все атрибуты:

<FrameLayout>
<TextView />
</FrameLayout>

Теперь давайте посмотрим, что такое FrameLayout.

FrameLayout

Все, что может FrameLayout — отображать View друг над другом (по оси Z). Вспомните курс математики, точнее, систему координат.

В двумерном пространстве есть две оси — X (слева направо) и Y (снизу вверх). В Android, кстати, это работает немного иначе — ось Y растет вниз, а не вверх.

Оси координат в Android
Оси координат в Android

В трёхмерном пространстве появляется ось Z, идущая "на нас". В контексте интерфейсов Z обозначает расположение элемента один над другим.

Давайте поэкспериментируем с FrameLayout. Замените TextView на такой View:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.lessons.MainActivity">

    <View
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:background="#ff0000" />

</FrameLayout>

Запустив приложение, вы увидите такую картинку:

FrameLayout
FrameLayout

Как видите, View расположился в верхнем левом углу — по умолчанию View позиционируются с точки (0, 0).

Обратите внимание на атрибуты у XML-тегов. Давайте рассмотрим их.

С помощью этого атрибута android:layout_width задается ширина элемента. Может принимать значения:

  • match_parent— занимает столько же места, сколько и родительский элемент.
  • wrap_content — занимает ровно столько места, сколько нужно, чтобы вместить весь контент внутри View.
  • Значение в пикселях (px), независимых от плотности пикселях (dp), пикселях, масштабируемых под размер шрифта (sp), дюймах (in) или миллиметрах (mm).

Пока что мы будем использовать только константы match_parent и wrap_content, а так же значения в dp. Что такое dp мы разберем попозже.

android:layout_height — то же самое, что android:layout_width, только для высоты.

FrameLayout должен занимать все пространство на экране, поэтому мы задали константу match_parent для ширины и высоты. В итоге, все белое пространство (и пространство под красным View) — это FrameLayout.

Для View же мы задали фиксированный размер в dp, поэтому он именно такого размера.

android:background — может принимать следующие значения:

  • ссылка на другой ресурс (об этом позже)
  • цвет в формате #rgb
  • цвет в формате #argb
  • цвет в формате #rrggbb
  • цвет в формате #aarrggbb

Мы задали цвет в формате #rrggbb, равный #ff0000, то есть красный.

В Android также есть такое понятие, как LayoutParams — параметры отображения View в контейнере. Они разные для каждого контейнера. Для FrameLayout LayoutParams содержат лишь один атрибут — android:layout_gravity. Этот атрибут позволяет задать расположение View внутри FrameLayout. Возможные значения:

  • bottom — объект "прижимается" к низу контейнера.
  • top — объект прижимается к верху контейнера.
  • left — объект прижимается к левой стороне контейнера. Использовать это значение не рекомендуется из-за отсутствия поддержки RTL-локалей.
  • right — объект прижимается к правой стороне контейнера. Использовать это значение не рекомендуется из-за отсутствия поддержки RTL-локалей.
  • start — объект прижимается к "началу" контейнера. В локалях с расположением элементов слева направо, LTR (то есть в большинстве) это аналог left, а в RTL — right.
  • end — объект прижимается к "концу" контейнера. В локалях с расположением элементов слева направо, LTR (то есть в большинстве) это аналог right, а в RTL — left.
  • center_horizontal — объект центрируется относительно контейнера по оси X.
  • center_vertical — объект центрируется относительно контейнера по оси Y.
  • center — объект располагается по центру контейнера.

Значения можно комбинировать, используя символ "|", например android:layout_gravity="end|bottom" в LTR локалях прижмет View в правый нижний угол, а в RTL — в левый нижний:

FrameLayout — View в правом нижнем углу
FrameLayout — View в правом нижнем углу

Изменим код на такой:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.lessons.MainActivity">

    <View
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:background="#ff0000" />

</FrameLayout>

Получим такой результат:

FrameLayout — View в центре
FrameLayout — View в центре

Теперь давайте разберемся, как FrameLayout выстраивает дочерние View по оси Z.

Добавим еще 2 View:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.lessons.MainActivity">

    <View
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:background="#ff0000" />

    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:background="#00ff00" />

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:background="#0000ff" />

</FrameLayout>

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

Запустите приложение:

FrameLayout: View друг над другом в центре
FrameLayout: View друг над другом в центре

Видно, что красный View находится ниже всех (он был объявлен первым), зеленый — над ним (он второй) и синий "выше" всех (он был объявлен последним).

Что мы еще можем сделать с этими View? Например, раскидать их по разным углам. Уменьшим размер всех View до 100dp и добавим еще один View:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.lessons.MainActivity">

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="start|top"
        android:background="#ff0000" />

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="end|top"
        android:background="#00ff00" />

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="start|bottom"
        android:background="#0000ff" />

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="end|bottom"
        android:background="#000000" />

</FrameLayout>

Получим вот такой результат:

FrameLayout: View по углам
FrameLayout: View по углам

Пожалуй, для этого урока хватит :)

В следующем уроке мы рассмотрим LinearLayout.



Вход

Войдите, чтобы пользоваться всеми преимуществами.
Это займёт всего пару секунд!

или