# Макеты ## Оглавление - [Введение](#введение) - [Редактор макетов](#редактор-макетов) - [Добавление компонентов на макет с помощью редактора](#добавление-компонентов-на-макет-с-помощью-редактора) - [Добавление `TextView`](#добавление-textview) - [Создание стиля `TextView`](#создание-стиля-textview) - [Добавление `ScrollView`](#добавление-scrollview) - [Добавление `EditText`](#добавление-edittext) - [Добавление `Button`](#добавление-button) - [Data Binding](#data-binding) - [ConstraintLayout](#constraintlayout) - [Интернационализация](#интернационализация) ## Введение Документация на layouts: https://developer.android.com/guide/topics/ui/declaring-layout. Макет определяет визуальную структуру пользовательского интерфейса, например, пользовательского интерфейса экрана или отдельного виджета. Существует два способа создания макета: * Объявление элементов UI в XML. В Android имеется удобный способ описания XML-элементов для классов `View` и их подклассов. * Программное создание экземпляров визуальных элементов путем наследования классов от `View` и его производных. В Android все классы визуальных элементов наследованы от `View`. От него унаследованы такие элементы как: * `TextView` — компонент для отображения текста, * `ImageView` — компонент для отображения изображения, * `Button` — стандартная кнопка, * `EditText` — компонент для ввода текста, * и другие компоненты, такие как `CheckBox`, `Slider`, `Menu` и др. Для размещения нескольких элементов на экране используются линейные макеты ([LinearLayout](https://developer.android.com/guide/topics/ui/layout/linear.html)). Разделяют горизонтальные и вертикальные макеты. Горизонтальные позволяют размещать элементы в ряд по горизонтали. Вертикальные — в столбик по вертикали, соответственно. Для изучения процесса создания макетов создадим простое приложение "About Me", отображающее информацию о пользователе, а также позволяющее ввести какую-нибудь дополнительную информацию. В Android Studio для редактирования макетов используется редактор дизайнов макетов, он будет далее рассмотрен. Кроме этого, будет рассмотрен способ передачи данных от элементов интерфейса к их программной реализации с помощью [Data Binding](#data-binding). Для дальнейшего изучения необходимо создать новый проект "About Me". Шаги по созданию были описаны в конспекте №2. ## Редактор макетов [Build a UI with Layout Editor](https://developer.android.com/studio/write/layout-editor.html) В проекте созданном по-умолчанию уже присутствует один файл с макетом. Это `activity_main.xml`. Здесь содержится компонент `LinearLayout` с контентом внутри. Файл макета располагается в каталоге `res/layout`, где располагаются все файлы макетов. Если кликнуть на файл дважды, откроется редактор макетов. Редактор макетов предоставляет графический интерфейс, упрощающий процесс построения макетов и размещения в них элементов интерфейса. Редактор содержит следующие панели: 1. **Palette** — список визуальных, элементов, которые можно добавить. 2. **Component Tree** — дерево уже добавленных макетов и компонентов в виде иерархии. 3. **Toolbar** — меню кнопок для настройки предварительного просмотра макета. 4. **Design editor** — основное окно редактора, отображающее макет с компонентами. 5. **Attributes** — панель с доступными свойствами и атрибутами текущего выбранного компонента с возможностью их редактирования. ![layout editor image](layout-editor.png) Для добавления новых компонентов из **Palette** можно переносить их как на макет в **Design editor**, так и в определенное место иерархии на **Component Tree**. Для переключения редактора к режиму редактирования XML-кода, необходимо выбрать вкладку **Text** внизу экрана редактора. ## Добавление компонентов на макет с помощью редактора Приложение "About Me" будет отображать имя и небольшое описание человека, а также возможность ввода и отображения никнейма. План: 1. Добавить текстовые поля для отображения имени и описания. 2. Добавить возможность скроллинга страницы, если текст не убирается на экран полностью. 3. Добавить текстовое поле для ввода никнейма. 4. Добавить кнопку для приема введенного никнейма. ### Добавление `TextView` Для добавления нового текстового поля необходимо в редакторе макетов взять элемент `TextView` из панели **Palette** и перенести на изображение экрана в **Design Editor**. На панели **Attributes** установить следующие параметры: * `id` = **name_text_view** — идентификатор элемента. * `layout_width` = **match_parent** — ширина элемента по ширине родителя, т.е. макета `LinearLayout`. * `layout_height` = **wrap_content** — высота элемента по высоте контента, т.е. отображаемого текста. * `text` = **Steve Jobs** — отображаемый текст. * `textSize` = **20sp** — размер шрифта, указывается в **sp** (scale-independent pixels) независимых от масштабирования пикселях. * `textColor` = **@android:color/black** — стандартный черный цвет. * `textAlignment` = **center** — разместить контент (текст) по центру элемента `TextView`. В Android принято хранить строки в отдельных ресурсах `strings`. Поэтому необходимо добавить текст с именем пользователя в отдельную строку: ```xml Steve Jobs ``` И указать в параметре `text` ссылку на добавленный ресурс **@strings/name**. Размеры также принято хранить в ресурсах для возможности переиспользования. Файлов ресурсов с размерами имеет имя `res/values/dimens.xml`. Если его нет в проекте, его необходимо создать и добавить новое значение с размером шрифта текста: ```xml 20sp ``` И также указать ссылку на ресурс **@dimen/text_size** в параметр `textSize`. ### Создание стиля `TextView` В ситуации, когда у нас есть множество однотипных текстовых полей или каких-либо других элементов интерфейса, удобным становится создание стилей элементов. Стиль — набор произвольных атрибутов, задающиеся разработчиком. Например, можно добавить для текстового поля шрифт (font family), отступы контента от края элемента (padding) и элемента от края макета (margin), а затем выделить атрибуты в отдельный стиль. Сперва добавим к `TextView` следующие атрибуты: * `fontFamily` = **sans-serif** — имя шрифта. * `paddingTop` = **@dimen/small_padding** — отступ текста от края верхнего элемента `TextView`, ссылка на предварительно добавленный ресурс с размером (**small_padding=8dp**). * `layout_marginTop` = **@dimen/layout_margin** — отступ `TextView` от верхнего края его родителя, т.е. элемента `LinearLayout`, ссылка на предварительно добавленный ресурс с размером **layout_margin=16dp**. Существует два способа добавления стиля: 1. Добавить стиль вручную в файл `values/styles.xml`. 2. Использовать редактор макетов для автоматического создания стиля. Для первого способа необходимо описать в файле `values/styles.xml` все атрибуты, которые необходимо объединить в стиль: ```xml ``` К элементу `TextView` необходимо добавить атрибут **style="@style/NameStyle"** для применения стиля. Для использования второго способа необходимо сперва перейти в редактор стилей. Затем нажать на элементе `TextView` на панели с добавленными элементами **Component Tree** правой кнопкой мыши, выбрать **Refactor** -> **Extract Style...**. Откроется диалоговое окно со списком атрибутов, необходимо проставить галочки у тех, которые необходимо выделить в отдельный стиль и указать его имя, например, "NameStyle". Таким образом стиль будет создан автоматически и добавлен в файл `values/styles.xml`, а атрибут **style** будет автоматически установлен в выбранный элемент `TextView`. ### Добавление `ScrollView` Когда на экране настолько много контента, что он не умещается, необходимо располагать контент внутри `ScrollView` для возможности скроллинга. В рамках приложения, добавим еще один `TextView`, который будет содержать достаточно длинное описание человека, чтобы оно не вмещалось на экране полностью. ```xml ``` Для нового элемента `TextView` также указывается созданный стиль "NameStyle", создается строковый ресурс **@string/bio** с длинным текстом, а также добавляется новый параметр **lineSpacingMultiplier** — множитель интервала между строками в тексте. Можно заметить, что добавленный текст располагается ровно от левого до правого края и это выглядит неаккуратно. Чтобы этого избежать Android Guidelines по дизайну предписывают добавление отступов от левого и правого края экрана. Для этого нужно добавить к корневому элементу атрибуты **paddingStart** и **paddingEnd**: ```xml android:paddingStart="@dimen/padding" android:paddingEnd="@dimen/padding" ``` Ресурс размера **@dimen/padding** берется равным **16dp** в данном примере. ### Добавление `EditText` Перейдем к добавлению текстового поля для ввода никнейма. Необходимо добавить элемент `EditText` на макет сразу после элемента `TextView` с именем (**id=name_text_view**). Можно сделать это вручную в XML, можно в редакторе макетов путем переноса элемента из панели **Palette** на панель **Component Tree**. Для элемента `EditText` необходимо задать атрибуты: * `id` = **nickname_edit_text**, * `layout_width` = **match_parent**, * `layout_height` = **wrap_content**, * `style` = **@style/NameStyle** — ссылка на стиль "NameStyle", * `textAlignment` = **center**, * `hint` = **@string/what_is_your_nickname** — подсказка для ввода текста, отображается в поле полупрозрачным шрифтом, ссылка на строковый ресурс со строкой "What is your nickname?" (строку необходимо предварительно добавить). Итоговый элемент должен быть следующим: ```xml ``` ### Добавление `Button` Ввод никнейма не должен быть бесполезным. Логично было бы его принять и отобразить как текст. Для этого необходимо добавить еще одно текстовое поле `TextView` для отображения никнейма, а также кнопку `Button` для принятия введенного в `EditText` никнейма и отображения его на новом `TextView`. Сперва добавим кнопку для принятия введенного никнейма. Кнопку требуется расположить следом за текстовым полем `EditText`. Кнопке присваиваются следующие атрибуты: * `id` = **done_button**, * `layout_width` = **wrap_content**, * `layout_height` = **wrap_content**, * `layout_gravity` = **center_horizontal** — расположить кнопку в центре по горизонтали относительно макета, * `fontFamily` = **sans-serif**, * `text` = **@string/done** — ссылка на строковый ресурс с текстом "Done", * `style` = **@style/Widget.AppCompat.Button.Colored** — ссылка на стандартный стиль, позволяющий делать кнопку цветной. Итоговый элемент: ```xml