page.title=Supporting Different Screen Sizes parent.title=Designing for Multiple Screens parent.link=index.html trainingnavtop=true next.title=Supporting Different Screen Densities next.link=screendensities.html @jd:body
NewsReader.zip
В этом уроке описаны следующие аспекты обеспечения совместимости интерфейса с разными экранами:
Чтобы создать масштабируемый макет, способный адаптироваться к разным экранам, используйте в качестве значений ширины и высоты отдельных компонентов представления параметры "wrap_content"
и "match_parent"
. Если используется "wrap_content"
, для ширины или высоты представления устанавливается минимальное значение, позволяющее уместить содержание на экран, а параметр "match_parent"
(известный как "fill_parent"
в API до 8 уровня) служит для растягивания компонента по размеру родительского представления.
Если указать параметры "wrap_content"
и "match_parent"
вместо строго заданных размеров, в представлениях будет использоваться минимально необходимое место или они будут растягиваться на всю доступную длину и ширину соответственно. Например:
Обратите внимание на то, что в коде учебного приложения размеры компонентов заданы с помощью параметров "wrap_content"
и "match_parent"
. В результате макет правильно отображается на экранах разных размеров при разных ориентациях.
Например, вот так он выглядит в вертикальной и горизонтальной ориентациях. Обратите внимание на то, как размеры компонентов автоматически адаптируются к длине и ширине:
Рисунок 1. Приложение News Reader при вертикальной (слева) и горизонтальной (справа) ориентации.
С помощью вложенных экземпляров объекта "wrap_content"
и "match_parent"
можно создавать достаточно сложные макеты. Однако
Например:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/label" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Type here:"/> <EditText android:id="@+id/entry" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/label"/> <Button android:id="@+id/ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/entry" android:layout_alignParentRight="true" android:layout_marginLeft="10dp" android:text="OK" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/ok" android:layout_alignTop="@id/ok" android:text="Cancel" /> </RelativeLayout>
На рис. 2 показано, как этот макет выглядит на экране QVGA.
Рисунок 2. Скриншот экрана QVGA (маленького размера).
На рис. 3 показано, как он выглядит на экране с большей диагональю.
Рисунок 3. Скриншот экрана WSVGA (большего размера).
Обратите внимание: несмотря на изменение размера компонентов их взаимное расположение остается прежним, так как оно задано объектом
Масштабируемые или относительные макеты, один из которых продемонстрирован выше, имеют свои ограничения. Хотя они позволяют создать интерфейс, способный адаптироваться к разным экранам за счет растягивания пространства внутри и вокруг компонентов, пользователю может оказаться не слишком удобно работать с таким интерфейсом. Поэтому в приложении должен использоваться не один масштабируемый макет, а несколько альтернативных вариантов для разных конфигураций экрана. Их можно создать с помощью квалификаторов конфигураций, которые позволяют оперативно выбирать ресурсы, отвечающие текущим параметрам экрана (например, разные варианты макетов для экранов разных размеров).
Многие приложения отображаются на больших экранах в двухпанельном режиме, при котором список элементов расположен в одной панели, а их содержание открывается в другой. Такой режим просмотра удобен на достаточно больших экранах планшетных ПК и телевизоров, однако на экране телефона эти панели следует отображать по отдельности. Для каждого режима просмотра нужно создать отдельный файл.
res/layout/main.xml
, однопанельный макет (по умолчанию):
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
res/layout-large/main.xml
, двухпанельный макет:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
Обратите внимание, что во втором случае в названии каталога использован квалификатор large
. Этот макет будет выбран на устройствах, экраны которых считаются большими (например, 7 дюймов и более). Первый макет (без квалификаторов) будет выбран для устройств с маленьким экраном.
Одной из проблем, с которой сталкивались разработчики приложений для устройств Android версий до 3.2, было слишком общее определение "большого" экрана. Это касалось устройств Dell Streak, первой модели Galaxy Tab и планшетных ПК с экраном размером 7 дюймов. Многие приложения требовалось по-разному отображать на разных устройствах (например, с 5- и 7-дюймовыми экранами), хотя они и относились к одной категории "больших" экранов. В Android версии 3.2 и более поздних доступен квалификатор Smallest-width.
Он позволяет определять экраны с заданной минимальной шириной в dp. Например, типичный планшетный ПК с экраном 7 дюймов имеет минимальную ширину 600 dp, и если вы хотите, чтобы приложение работало на нем в двухпанельном режиме (а на меньших экранах в однопанельном), используйте два макета из предыдущего раздела, но вместо квалификатора размера large
укажите sw600dp
. В таком случае на экранах, минимальная ширина которых составляет 600 dp, будет использоваться двухпанельный макет.
res/layout/main.xml
, однопанельный макет (по умолчанию):
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
res/layout-sw600dp/main.xml
, двухпанельный макет:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
Это означает, что на устройствах, минимальная ширина экрана которых не меньше 600 dp, будет выбран layout-sw600dp/main.xml
(двухпанельный макет), а на экранах меньшего размера – layout/main.xml
(однопанельный макет).
Следует учесть, что на Android-устройствах до версии 3.2 квалификатор sw600dp
не будет работать, поэтому для них по-прежнему нужно использовать large
. Таким образом, вам потребуется еще один файл с названием res/layout-large/main.xml
, идентичный файлу res/layout-sw600dp/main.xml
. В следующем разделе вы познакомитесь с методом, который позволяет избежать дублирования таких файлов макета.
Квалификатор Smallest-width работает только на устройствах Android 3.2 или более поздних версий. Для совместимости с более ранними устройствами по-прежнему следует использовать абстрактные размеры (small, normal, large и xlarge). Например, чтобы интерфейс открывался в однопанельном режиме на телефонах и в многопанельном на планшетных ПК с 7-дюймовым экраном, телевизорах и других крупных устройствах, подготовьте следующие файлы:
res/layout/main.xml:
однопанельный макет;res/layout-large:
многопанельный макет;res/layout-sw600dp:
многопанельный макет.Последние два файла идентичны: один из них предназначен для устройств Android 3.2 и новее, а второй для более старых планшетных ПК и телевизоров на платформе Android.
Чтобы не создавать дубликаты файлов и упростить процесс поддержки приложения, используйте псевдонимы. Например, можно определить следующие макеты:
res/layout/main.xml
(однопанельный макет);res/layout/main_twopanes.xml
(двухпанельный макет).Затем добавьте следующие два файла:
res/values-large/layout.xml
:
<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
res/values-sw600dp/layout.xml
:
<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
Содержание последних двух файлов одинаково, но сами по себе они не определяют макет. Они служат для того, чтобы назначить файл large
и sw600dp
, они применяются к планшетным ПК и телевизорам на платформе Android независимо от версии (для версий до 3.2 используется
sw600dp
).
Хотя некоторые макеты одинаково хорошо смотрятся в вертикальной и горизонтальной ориентациях, в большинстве случаев интерфейс все же приходится адаптировать. Ниже показано, как изменяется макет в приложении News Reader в зависимости от размера и ориентации экрана.
Каждый из этих макетов определен в XML-файле в каталоге res/layout/
. Чтобы сопоставить их с определенными конфигурациями экрана, в приложении используются псевдонимы:
res/layout/onepane.xml:
res/layout/onepane_with_bar.xml:
res/layout/twopanes.xml
:
res/layout/twopanes_narrow.xml
:
После того как все возможные макеты определены, остается сопоставить каждый из них с подходящей конфигурацией, используя квалификаторы конфигураций. Воспользуемся псевдонимами макетов:
res/values/layouts.xml
:
res/values-sw600dp-land/layouts.xml
:
res/values-sw600dp-port/layouts.xml
:
res/values-large-land/layouts.xml
:
res/values-large-port/layouts.xml
:
Чтобы интерфейс был совместим с экранами разных размеров, используемые в нем графические элементы также должны быть адаптированы соответствующим образом. Например, фон кнопки должен одинаково хорошо выглядеть независимо от ее формы.
Если использовать для компонентов, размеры которых меняются, обычные изображения, то они будут равномерно сжиматься и растягиваться, и результат будет далек от идеального. Решением являются растровые изображения формата nine-patch – специальные PNG-файлы, содержащие информацию о том, какие области можно растягивать, а какие нет.
Создавая растровые изображения для масштабируемых компонентов, обязательно используйте формат nine-patch. На рис. 4 показано обычное растровое изображение (увеличенное в 4 раза для наглядности), которое мы переведем в формат nine-patch.
Рисунок 4. button.png
Откройте его с помощью утилиты draw9patch
, входящей в комплект разработчика (в каталоге tools/
). Установите метки на левом и верхнем краях, чтобы ограничить области, которые можно растягивать. Можно также провести линию вдоль правого и нижнего краев, как показано на рис. 5, чтобы отметить области, в которых содержание должно быть зафиксировано.
Рисунок 5. button.9.png
Обратите внимание на черные пиксели по краям. Метки у верхней и левой границ обозначают те области, которые можно растягивать, а метки у правой и нижней границ – те, куда должно быть помещено содержание.
Также обратите внимание на расширение .9.png
. Оно должно быть задано именно в таком виде, чтобы система могла определить, что это формат nine-patch, а не обычный PNG-файл.
При применении этого фона к компоненту (с помощью android:background="@drawable/button"
) изображение будет растянуто по размеру кнопки, как показано на рис. 6.
Рисунок 6. Кнопки разных размеров с файлом фона button.9.png
в формате nine-patch.