Найти в Дзене
OIntelligence

AndroidDev. Layout

Оглавление

Layout часть Android Jetpack. Layout (макет) определяет структуру пользовательского интерфейса в вашем приложении, например в activity. Все элементы Layout построены с использованием иерархии объектов View и ViewGroup. View обычно отображает что-то, что пользователь может видеть и с чем может взаимодействовать. Принимая во внимание, что ViewGroup — это невидимый контейнер, который определяет структуру макета для View и других объектов ViewGroup, как показано на рисунке 1.

Рисунок 1. иерархия представлений, которая определяет макет пользовательского интерфейса
Рисунок 1. иерархия представлений, которая определяет макет пользовательского интерфейса

Объекты View обычно называются «виджетами» и могут быть одним из многих подклассов, таких как Button или TextView. Объекты ViewGroup, обычно называемые «макетами», могут быть одним из многих типов, обеспечивающих различную структуру макета, например LinearLayout или ConstraintLayout .

Вы можете объявить макет двумя способами:

  • Объявите элементы пользовательского интерфейса в XML. Android предоставляет простой словарь XML, соответствующий классам и подклассам View, например, для виджетов и макетов.
    Вы также можете использовать редактор макетов Android Studio для создания макета XML с помощью интерфейса перетаскивания.
  • Создание экземпляров элементов Layout во время выполнения. Ваше приложение может программно создавать объекты View и ViewGroup (и управлять их свойствами).

Объявление вашего пользовательского интерфейса в XML позволяет вам отделить представление вашего приложения от кода, управляющего его поведением. Использование XML-файлов также позволяет легко предоставлять различные макеты для экранов разных размеров и ориентаций (подробнее обсуждается в разделе «Поддержка различных размеров экрана»). Платформа Android дает вам возможность использовать один или оба этих метода для создания пользовательского интерфейса вашего приложения. Например, вы можете объявить макеты вашего приложения по умолчанию в XML, а затем изменить макет во время выполнения.

Совет. Для отладки макета во время выполнения используйте Layout Inspector tool

Пишем XML

Используя XML-лексикон Android, вы можете быстро создавать макеты пользовательского интерфейса и элементы экрана, которые они содержат, точно так же, как вы создаете веб-страницы в HTML — с рядом вложенных элементов.

Каждый файл макета должен содержать ровно один корневой элемент, который должен быть объектом View или ViewGroup. После того как вы определили корневой элемент, вы можете добавить дополнительные объекты макета или виджеты в качестве дочерних элементов, чтобы постепенно построить иерархию представлений, определяющую ваш макет. Например, вот макет XML, который использует вертикальный LinearLayout для хранения TextView и Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

После того как вы объявили свой макет в XML, сохраните файл с расширением .xml в каталоге res/layout/ вашего проекта Android, чтобы он правильно скомпилировался. Дополнительные сведения о синтаксисе XML-файла макета доступны в документе Ресурсы макета.

Загрузка XML-ресурсов

При компиляции приложения каждый XML-файл макета компилируется в ресурс View. Вы должны загрузить ресурс макета из кода своего приложения в реализации обратного вызова Activity.onCreate(). Сделайте это, вызвав setContentView(), передав ему ссылку на ваш ресурс макета в виде: R.layout.layout_file_name. Например, если ваш макет XML сохранен как main_layout.xml, вы должны загрузить его для своей деятельности следующим образом:

// Kotlin
fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

Метод обратного вызова onCreate() в Activity вызывается платформой Android при запуске Activity (см. обсуждение жизненных циклов в документе Activity).

Атрибуты

Каждый объект View и ViewGroup поддерживает собственный набор XML-атрибутов. Некоторые атрибуты специфичны для объекта View (например, TextView поддерживает атрибут textSize), но эти атрибуты также наследуются любыми объектами View, которые могут расширять этот класс. Некоторые из них являются общими для всех объектов View, поскольку они унаследованы от корневого класса View (например, атрибут id). И другие атрибуты считаются «параметрами макета», которые представляют собой атрибуты, описывающие определенные ориентации макета объекта View, определенные родительским объектом ViewGroup этого объекта.

ID

Любой объект представления может иметь связанный с ним целочисленный идентификатор для уникальной идентификации представления в дереве. Когда приложение компилируется, на этот идентификатор ссылаются как на целое число, но идентификатор обычно назначается в XML-файле макета в виде строки в атрибуте id. Это XML-атрибут, общий для всех объектов View (определяемых классом View), и вы будете использовать его очень часто. Синтаксис идентификатора внутри тега XML:

android:id="@+id/my_button"

Символ at (@) в начале строки указывает, что синтаксический анализатор XML должен проанализировать и расширить остальную часть строки идентификатора и идентифицировать ее как ресурс идентификатора. Символ плюса (+) означает, что это новое имя ресурса, которое необходимо создать и добавить к нашим ресурсам (в файле R.java). Существует ряд других ресурсов ID, предлагаемых платформой Android. При ссылке на идентификатор ресурса Android вам не нужен символ плюса, но вы должны добавить пространство имен пакета Android, например:

android:id="@android:id/empty"

Имея пространство имен пакетов Android, мы теперь ссылаемся на идентификатор из класса ресурсов android.R, а не из класса локальных ресурсов.

Для создания представлений и ссылки на них из приложения обычно используется следующий шаблон:

1. Определите представление/виджет в файле макета и назначьте ему уникальный идентификатор:

<Button android:id="@+id/my_button"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="@string/my_button_text"/>

2. Затем создайте экземпляр объекта представления и захватите его из макета (обычно в методе onCreate()):

val myButton: Button = findViewById(R.id.my_button)

Определение идентификаторов для объектов представления важно при создании RelativeLayout. В относительном макете одноуровневые представления могут определять свой макет относительно другого одноуровневого представления, на которое ссылается уникальный идентификатор.

Идентификатор не обязательно должен быть уникальным во всем дереве, но он должен быть уникальным в той части дерева, которую вы ищете (часто это может быть все дерево, поэтому по возможности лучше быть полностью уникальным).

Примечание. В Android Studio 3.6 и более поздних версиях функция привязки представления может заменить вызовы findViewById() и обеспечивает безопасность типов во время компиляции для кода, взаимодействующего с представлениями. Рассмотрите возможность использования привязки представления вместо findViewById().

Параметры Layout

Атрибуты макета XML с именем layout_something определяют параметры макета для представления, подходящие для группы представлений, в которой оно находится.

Каждый класс ViewGroup реализует вложенный класс, который расширяет ViewGroup.LayoutParams. Этот подкласс содержит типы свойств, которые определяют размер и положение для каждого дочернего представления в соответствии с группой представлений. Как видно на рисунке 2, родительская группа представлений определяет параметры макета для каждого дочернего представления (включая дочернюю группу представлений).

Рисунок 2. Визуализация иерархии представлений с параметрами макета, связанными с каждым представлением
Рисунок 2. Визуализация иерархии представлений с параметрами макета, связанными с каждым представлением

Обратите внимание, что каждый подкласс LayoutParams имеет собственный синтаксис для установки значений. Каждый дочерний элемент должен определять LayoutParams, подходящие для его родителя, хотя он также может определять разные LayoutParams для своих собственных дочерних элементов.

Все группы представлений включают ширину и высоту (layout_width и layout_height), и каждое представление необходимо для их определения. Многие LayoutParams также включают необязательные поля и границы.

Вы можете указать ширину и высоту с точными размерами, хотя, вероятно, вам не захочется делать это часто. Чаще вы будете использовать одну из этих констант для установки ширины или высоты:

  • wrap_content сообщает вашему представлению о том, что размер должен соответствовать размерам, требуемым его содержимым.
  • match_parent сообщает, что ваше представление становится настолько большим, насколько позволяет его родительская группа представлений.

Как правило, указывать ширину и высоту макета в абсолютных единицах измерения, таких как пиксели, не рекомендуется. Вместо этого использование относительных измерений, таких как независимые от плотности пиксельные единицы (dp), wrap_content или match_parent, является лучшим подходом, поскольку это помогает гарантировать, что ваше приложение будет правильно отображаться на различных размерах экрана устройства. Допустимые типы измерений определены в документе «Доступные ресурсы».

Положение Layout

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

Можно получить местоположение представления, вызвав методы getLeft() и getTop(). Первый возвращает левую, или X, координату прямоугольника, представляющего вид. Последний возвращает верхнюю координату Y прямоугольника, представляющего представление. Оба этих метода возвращают расположение представления относительно его родителя. Например, когда getLeft() возвращает 20, это означает, что представление расположено на 20 пикселей правее левого края его прямого родителя.

Кроме того, предлагается несколько удобных методов, позволяющих избежать ненужных вычислений, а именно getRight() и getBottom(). Эти методы возвращают координаты правого и нижнего краев прямоугольника, представляющего представление. Например, вызов getRight() аналогичен следующему вычислению: getLeft() + getWidth().

Размер, отступы и поля

Размер представления выражается шириной и высотой. Представление фактически имеет две пары значений ширины и высоты.

Первая пара известна как измеренная ширина и измеренная высота. Эти размеры определяют, насколько большим должно быть представление внутри своего родителя. Измеренные размеры можно получить, вызвав методы getMeasuredWidth() и getMeasuredHeight().

Вторая пара известна просто как ширина и высота, или иногда ширина и высота рисунка. Эти размеры определяют фактический размер вида на экране во время рисования и после компоновки. Эти значения могут, но не обязательно, отличаться от измеренных ширины и высоты. Ширину и высоту можно получить, вызвав методы getWidth() и getHeight().

Чтобы измерить свои размеры, представление принимает во внимание его отступы. Заполнение выражается в пикселях для левой, верхней, правой и нижней частей представления. Заполнение можно использовать для смещения содержимого представления на определенное количество пикселей. Например, левый отступ, равный 2, сдвинет содержимое представления на 2 пикселя вправо от левого края. Заполнение можно установить с помощью метода setPadding(int, int, int, int) и запросить, вызвав getPaddingLeft(), getPaddingTop(), getPaddingRight() и getPaddingBottom().

Несмотря на то, что представление может определять отступы, оно не обеспечивает никакой поддержки полей. Тем не менее, просмотр предоставляет такие группы, как поддержка. Обратитесь к ViewGroup и ViewGroup.MarginLayoutParams для получения дополнительной информации.

Дополнительные сведения об измерениях см. в разделе Значения измерений.

Основные Layouts

Каждый подкласс класса ViewGroup предоставляет уникальный способ отображения вложенных в него представлений. Ниже приведены некоторые из наиболее распространенных типов макетов, встроенных в платформу Android.

Примечание. Хотя вы можете вложить один или несколько макетов в другой макет для достижения своего дизайна пользовательского интерфейса, вы должны стремиться к тому, чтобы ваша иерархия макетов была как можно более мелкой. Ваш макет отрисовывается быстрее, если в нем меньше вложенных макетов (иерархия широкого представления лучше, чем иерархия глубокого представления).

Linear Layout

-3

Макет, который организует свои дочерние элементы в один горизонтальный или вертикальный ряд. Он создает полосу прокрутки, если длина окна превышает длину экрана.

Relative Layout

-4

Позволяет указать расположение дочерних объектов относительно друг друга (дочерний объект A слева от дочернего объекта B) или относительно родительского объекта (выровнен по верхней части родительского объекта).

Web View

-5

Отображает веб-страницы.

Построение Layouts с помощью адаптера

Если содержимое вашего макета является динамическим или не задано заранее, вы можете использовать макет, который является подклассом AdapterView, для заполнения макета представлениями во время выполнения. Подкласс класса AdapterView использует адаптер для привязки данных к его макету. Адаптер действует как посредник между источником данных и макетом AdapterView — адаптер извлекает данные (из такого источника, как массив или запрос к базе данных) и преобразует каждую запись в представление, которое можно добавить в макет AdapterView.

Основные Layouts, поддерживаемые адаптером, включают:

List View

-6

Отображает прокручиваемый список из одного столбца.

Grid View

-7

Отображает прокручивающуюся сетку столбцов и строк.

Заполнение представления адаптера данными

Вы можете заполнить AdapterView, например ListView или GridView, привязав экземпляр AdapterView к адаптеру, который извлекает данные из внешнего источника и создает представление, представляющее каждую запись данных.

Android предоставляет несколько подклассов адаптера, которые полезны для получения различных типов данных и построения представлений для адаптера. Два наиболее распространенных адаптера:

ArrayAdapter

Используйте этот адаптер, если источником данных является массив. По умолчанию ArrayAdapter создает представление для каждого элемента массива, вызывая toString() для каждого элемента и помещая содержимое в TextView.

Например, если у вас есть массив строк, который вы хотите отобразить в ListView, инициализируйте новый ArrayAdapter с помощью конструктора, чтобы указать макет для каждой строки и массива строк:

// Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)

Аргументы для этого конструктора:

  • Контекст вашего приложения
  • Макет, содержащий TextView для каждой строки в массиве
  • Массив строк

Затем просто вызовите setAdapter() в вашем ListView:

// Kotlin
val listView: ListView = findViewById(R.id.listview)
listView.adapter = adapter

Чтобы настроить внешний вид каждого элемента, вы можете переопределить метод toString() для объектов в вашем массиве. Или, чтобы создать представление для каждого элемента, отличное от TextView (например, если вам нужен ImageView для каждого элемента массива), расширьте класс ArrayAdapter и переопределите getView(), чтобы возвращать тип представления, который вы хотите для каждого элемента.

SimpleCursorAdapter

Используйте этот адаптер, когда ваши данные поступают от курсора. При использовании SimpleCursorAdapter необходимо указать макет, который будет использоваться для каждой строки курсора, и какие столбцы курсора должны быть вставлены в какие представления макета. Например, если вы хотите создать список имен людей и телефонных номеров, вы можете выполнить запрос, который возвращает курсор, содержащий строку для каждого человека и столбцы для имен и номеров. Затем вы создаете массив строк, указывающий, какие столбцы из курсора вы хотите использовать в макете для каждого результата, и целочисленный массив, указывающий соответствующие представления, в которые должен быть помещен каждый столбец:

// Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER)
val toViews = intArrayOf(R.id.display_name, R.id.phone_number)

Когда вы создаете экземпляр SimpleCursorAdapter, передайте макет для использования для каждого результата, Cursor, содержащий результаты, и эти два массива:

// Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0)
val listView = getListView()
listView.adapter = adapter

Затем SimpleCursorAdapter создает представление для каждой строки в Cursor, используя предоставленный макет, вставляя каждый элемент fromColumns в соответствующее представление toViews.

Если в течение жизни вашего приложения вы измените базовые данные, считываемые вашим адаптером, вы должны вызвать notifyDataSetChanged(). Это уведомит прикрепленное представление о том, что данные были изменены, и оно должно обновиться.

Обработка событий кликов

Вы можете реагировать на события щелчка по каждому элементу в AdapterView, реализуя интерфейс AdapterView.OnItemClickListener. Например:

// Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Делаем что-то в ответ на клик
}

Дополнительные ресурсы

Использование layouts в демонстрационном приложении Sunflower.

-8

источник: https://developer.android.com/guide/topics/ui/declaring-layout

#android developments #android studio #layout #kotlin