LiteCoding

Заметки о программировании

Верстка для Android. Часть 1. Единая система измерений.

without comments

В рекомендациях от Google есть ряд полезных советов, используя которые можно найти хорошие решения проблемы верстки под все многообразие разрешений экрана, встречающихся на аппаратах с Android. Но для начала нужно понять, в чем именно заключается вся сложность верстки. У нас есть 10 разрешений, несколько типичных размеров экранов (включая планшеты с диагоналями 7 и 10 дюймов), несколько значений плотности размещения точек на экране. Все эти величины связаны между собой жесткими соотношениями.

Опираться только на разрешение экрана очень опасно, поскольку экраны с одним разрешением, но разной плотностью размещения точек имеют разные размеры. Так можно оказаться в ситуации, когда элемент графического интерфейса будет мелким и неудобным в использовании. Решение в данном случае есть, и оно довольно простое — использовать dip (density-independent pixel) в качестве единицы измерений. Dip — это логическая точка, которая позволяет не задумываться о плотности размещения физических точек. Формула, связывающая эти величины, проста:

pixels = dps * (density / 160)

pixels — размер в физических точках
dps — размер в логических точках (dip)
density — плотность размещения элементов экрана в физических точках на дюйм

Рекомендации, на которые я сослался в самом начале, выражены в следующих 4х пунктах:

  • Использовать wrap_content, fill_parent или dip вместо физических точек
  • Не использовать AbsoluteLayout
  • Не использовать физические точки в коде
  • Использовать ресурсы, специфичные для разных параметров экрана

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

Второй пункт носит больше методический характер, нежели практический. Класс данного контейнера объявлен устаревшим, потому он может в будущем исчезнуть из SDK и сред исполнения. К тому же, без этого класса можно обойтись. Путем несложных манипуляций точно такой же эффект получается с помощью FrameLayout или RelativeLayout.

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

Если в нашем приложении есть экран без прокрутки (например, экран с иконками в официальном клиенте твиттера), есть смысл попробовать прием, описанный ниже.

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

После пересчета физических точек в логические мы получим очень интересный результат — количество разрешений сократилось с 8 до 7 (точнее, с 10 до 9, т.к. в таблице не представлены mdpi-экраны с разрешением 1024×576 и 1024×600). И это уже хороший результат, но можно добиться лучшего. В большинстве случаев две неширокие неактивные полосы (в отличие, от «обрезанного» экрана) не вызовут дискомфорта у пользователей. Именно поэтому мы можем группировать близкие логические разрешения. Например, так:

  • 320×426(.6)
  • 320×480
  • 320×533(.3)
  • 320×569(.3), 320×576
  • 480×800, 480×856
  • 1024×576, 1024×600

Также можно объединить первую группу со второй, а третью — с четвертой. Конечное разбиение на группы зависит от каждого конкретного приложения, для которого все выполняется. Для каждой из групп понадобится сетка расположения элементов (т.е. смещения и размеры в логических точках) на наименьшем логическом разрешении группы. По этой каждой сетке создается XML-файл с размещением элементов.

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

Далее я покажу пример для следующих групп:

  • 320×426(.6), 320×480
  • 320×533(.3), 320×569(.3), 320×576
  • 480×800, 480×856
  • 1024×576, 1024×600

В первой группе у нас находятся экраны с низкой и средней плотностью, и оба не являются «длинными» (соотношение меньшей стороны к большей лежит в диапазоне 0.66..1), в отличие от всех остальных, поэтому для нее правильный путь к XML следующий: res/layout-notlong/layout.xml. Если первую группу придется разбивать, правильные спецификаторы будут следующими: small-notlong (или просто small) и normal-notlong (можно normal-notlong-mdpi).

Точно так же для второй группы следует выбрать спецификатор normal (поскольку спецификатор предыдущей группы notlong более узкий, нежели normal) или normal-long. Третью группу описывает спецификатор large, а четвертую — xlarge.

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

Остается единственный вопрос: как разместить сверстанный блок элементов по центру экрана и что делать с пустым местом по краям экрана?

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:gravity="center_vertical|center_horizontal"
  android:background="#ffff0000" >
	<RelativeLayout 
	  android:layout_width="320dip"
	  android:layout_height="426dip"
	  android:gravity="center_vertical|center_horizontal"
	  android:background="#ff000000" >
		<TextView 
		  android:textColor="#ffffffff" 
		  android:text="Hello from LiteCoding.com" 
		  android:typeface="monospace" 
		  android:layout_height="wrap_content" 
		  android:layout_width="wrap_content" />
	</RelativeLayout>
</RelativeLayout>

А оценить разницу в изображении на экранах первой группы можно на следующих скриншотах (серая рамка к экрану не относится, «подложка» имеет красный фон, рабочая область — черный):

Следующая статья: Верстка для Android. Часть 2. «Табличная» верстка.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • Tumblr

Written by Дмитрий Воробьев

Среда, Декабрь 15th, 2010 at 05:13

Leave a Reply

You must be logged in to post a comment.