Раздел: Разметка (layout)

Разметка(layout)

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

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

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

  • Плагин ADT для Eclipse поддерживает предпросмотр XML разметки.
  • Попробуйте также утилиту Hierarchy Viewer для отладки разметки.
  • Инструмент layoutopt позволяет проводить быстрый анализ разметки и иерархии для поиска неэффективных решений и других проблем.

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

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

Создание XML

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

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

[crayon-589755754faaa516186313/]

Сохраните файл разметки с разрешением .xml в директории res/layout/ вашего проекта. Подробная информация о синтаксисе XML разметки содержится в разделе Ресурс разметки.

Загрузка XML ресурса

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

[crayon-589755754fabd202091340/]

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

Атрибуты

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

ID

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

[crayon-589755754fac5377940426/]

Символ собачка "@" указывает XML парсеру, что перед ним идентификатор ресурса. Символ плюс "+" указывает, что данный ресурс новый и для него должен быть добавлен объект в файле R.java. Android предоставляет ряд встроенных ресурсов. При ссылке на них не нужно указывать знак "+", но необходимо добавлять название пакета android:

[crayon-589755754facb220003087/]

Добавляя название пакета android, мы таким образом ссылаемся на ресурсы класса android.R, а не на локальный класс ресурсов.

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

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

    [crayon-589755754fad1360314089/]
  2. Затем создайте экземпляр объекта нужного типа и установите для него разметку следующим образом:

    [crayon-589755754fad7992639026/]

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

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

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

XML атрибуты разметки с именем layout_что-нибудь описывают параметры разметки, подходящие для контейнера ViewGroup, в котором располагается элемент View.

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

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

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

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

Вы можете указать ширину и высоту с помощью конкретных цифр, однако чаще всего вы будете использовать следующие ключевые слова:

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

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

Позиция разметки

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

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

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

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

Размер задается с помощью пары ширина и высота. На самом деле компонент имеет две пары ширины и высоты.

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

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

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

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

Подробнее об измерениях смотрите в разделе Другие типы ресурсов.

Популярные контейнеры разметки

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

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

Линейная разметка (LinearLayout)

Группа для организации элементов по вертикали или горизонтали. Создает полосу прокрутки, если элементы не умещаются.

Относительная разметка (RelativeLayout)

Группа, позволяющая указать расположение элемента относительно его соседей.

WebView

Показывает web-страницы.

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

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

Вот два наиболее популярных типа разметки для работы с адаптером:

ListView

Прокручиваемый список элементов.

GridView

Прокручиваемая сетка (таблица) элементов.

Заполнение контейнера с помощью адаптера

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

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

ArrayAdapter

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

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

[crayon-589755754faf6545531175/]

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

  • Context приложения.
  • Разметку, которая содержит TextView для строк массива.
  • Строковый массив.

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

[crayon-589755754fafd441316560/]

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

SimpleCursorAdapter

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

[crayon-589755754fb05468444115/]

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

[crayon-589755754fb0b695902845/]

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

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

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

[crayon-589755754fb11651571836/]