lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Макеты

Макет определяет визуальную структуру пользовательского интерфейса, например, пользовательского интерфейса операции или виджета приложения. Существует два способа объявить макет:

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

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

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

Как правило, справочник XML-элементов для объявления элементов пользовательского интерфейса точно следует структуре и правилам именования для классов и методов — названия элементов соответствуют названиям классов, а названия атрибутов соответствуют методам. Фактически, соответствие зачастую такое точное, что вы можете с легкостью догадаться, какой атрибут XML соответствует тому или иному методу класса, или какой класс соответствует заданному элементу XML. Однако следует отметить, что не все справочники являются идентичными. В некоторых случаях названия могут несколько отличаться. Например, у элемента EditText есть атрибут text, который соответствует методу EditText.setText().

Совет. Дополнительные сведения о различных типах макетов представлены в разделе Часто используемые макеты. Также в инструкциях по построению объектов представления Hello изложены сведения о создании различных макетов.

Создание 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, загрузить его для вашей операции необходимо следующим образом:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

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

Атрибуты

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

Идентификатор

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

android:id="@+id/my_button"

Символ @ в начале строки указывает на то, что обработчику XML следует выполнить синтаксический анализ остальной части идентификатора, выполнить ее синтаксический анализ и определить ее в качестве ресурса идентификатора. Символ плюса (+) обозначает, что это имя нового ресурса, который необходимо создать и добавить к нашим ресурсам (в файле R.java). В 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()):
    Button myButton = (Button) findViewById(R.id.my_button);
    

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

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

Параметры макета

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

Каждый класс ViewGroup реализует вложенный класс, который наследует ViewGroup.LayoutParams. В этом подклассе имеются типы свойств, которые определяют размер и положение каждого дочернего представления, подходящие для его группы. На рисунке 1 показано, что родительская группа представлений определяет параметры макета для каждого дочернего представления (включая дочернюю группу представлений).

Рисунок 1. Графическое представление иерархии представления с параметрами макета каждого представления.

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

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

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

  • wrap_content — размер представления задается по размерам его содержимого;
  • match_parent (которая до API уровня 8 называлась fill_parent ) — размер представления определяется ограничениями, задаваемыми его родительской группой представлений.

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

Размещение макета

Представление имеет прямоугольную форму. Расположение представления определяется его координатами слева и сверху, а его размеры — параметрами ширины и высоты. Расположение измеряется в пикселах.

Расположение представления можно получить путем вызова методов 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.

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

Часто используемые макеты

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

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

Линейный макет

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

Относительный макет

В этом макете можно задавать расположение дочерних объектов относительно друг друга (дочерний элемент А находится слева от дочернего элемента Б) или относительно родительского объекта (выравнивание относительно верхнего края родительского элемента).

Представление веб-страницы

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

Создание макетов с помощью адаптера

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

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

Представление в виде списка

Отображение списка в один столбец с возможностью прокрутки.

Представление в виде сетки

Отображение сетки из столбцов и строк с возможностью прокрутки.

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

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

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

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

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

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, myStringArray);

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

  • ваше приложение Context;
  • макет, в котором содержится объект TextView для каждой строки в массиве;
  • массив строк.

Затем достаточно вызвать метод setAdapter() для своего объекта ListView:

ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);

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

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

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                        ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};

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

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);

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

.

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

Обработка нажатий

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

// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click
    }
};

listView.setOnItemClickListener(mMessageClickedHandler);