» Программирование Android

«Правильный» дизайн Android-приложений

Очень часто складывается впечатление, что разработчики даже некоторых весьма популярных и мощных приложений для Android никогда не слышали о User Interface Guidelines. Однако следовать рекомендациям от создателей мобильной ОС не так-то сложно и часто полезно и эффективно. Почему так, мы сейчас и разберемся.

Мы рассмотрим некоторые ключевые элементы проектирования приложения для операционной системы Android, а за основу и как пример будем модифицировать всем известный код «Hello World». Конкретнее, пояснения коснуться таких составляющих, как создание всплывающего меню, окна настроек, а также работа с Nine-patch hraphics.

Приступим. Для начала необходимо создать сам проект, назовем его AdvancedHelloWorld. Если никакая специфическая функциональность той или иной версии операционной системы не используется, то удобно ставить как Build Target Android 1.6, а MinSDKversion равным 3. Таким образом, одновременно будет работать разделение ресурсов приложения в зависимости от детализации экрана (hdpi, mdpi, ldpi), в то же время не будут забыты и девайсы с Android 1.5.

Что касается ресурсов для устройств с разными по разрешающей способности дисплеями, то оптимально использовать свой набор графики для hdpi, и отдельный – для всех остальных устройств, в разрешении, которое адаптировано под mdpi. То есть, не нужно сразу бросаться на адаптацию под ldpi, к тому же таких устройств все-равно немного. В крайнем случае, такую адаптацию можно сделать, но уже в последнюю очередь, после создания всей программной части. Как бы там ни было, если в приложении есть поддержка Android версии 1.5 – а мы её указали, то в директории drawable должны присутствовать все графические элементы программы.

В файле res/layout/main.xml создает одну единственную кнопку – «Say hello». Иконку для нашей программы создаем при помощи утилиты Android Asset Studio. Как обработчик нажатия кнопки вставляем код, который выведет на экран Toast-сообщение «Hello World».

Описание всплывающего меню задается в .xml-файлах. Создадим для главного окна файл res/menu/main_menu.xml:

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@+id/menu_preferences"

android:icon="@drawable/ic_menu_preferences"

android:title="@string/menu_preferences" />

<item android:id="@+id/menu_theme"

android:icon="@drawable/ic_menu_theme"

android:title="@string/menu_theme" />

<item android:id="@+id/menu_close"

android:icon="@drawable/ic_menu_close_clear_cancel"

android:title="@string/menu_close" />

</menu>

Что важно, так это то, что при наличие больше шести пунктов меню, шестой и все последующие пункты будут выделены отдельно в меню «дополнительно» — как в стоковом браузере, например. Меню также может быть вложенным, но иметь не больше одного уровня. Чтобы описать вложенное меню, нужно добавить тег <menu> как дочерний по отношению к элементу, который будет разворачиваться в это самое меню.

Создавая меню, в первую очередь стоит искать иконки в стандартном их наборе. Они все есть в Android SDK (при установке по умолчанию, путь C:android-sdk-windowsplatformsandroid-1.6data
esdrawableic_menu_*.png
). Иконку для «настроек» и «выхода» выбрать проблем не составит, но для пущей наглядности примера также подберем иконку для созданного пункта «тема», который будет производить переключение цвета фона с черного на белый и наоборот. Пускай шаблон будет иметь вот такой вид:

Как видно, такую картинку можно без проблем нарисовать хоть в «пейнте». Дальше используем упомянутую Android Asset Studio и получаем неплохую иконку:

Создание пунктов меню осуществляется в onCreateOptionsMenu:

@Override

public boolean onCreateOptionsMenu(Menu menu) {

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.main_menu, menu);

return true;

}

Обработка нажатий на кнопки – также в onCreateOptionsMenu:

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case R.id.menu_preferences:

...

default:

return super.onOptionsItemSelected(item);

}

}

Чтобы спроектировать наше окно настроек, создаем файл res/xml/settings.xml, и вписываем туда следующие строки кода:

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen

xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory

android:title="@string/settings_general">

<CheckBoxPreference

android:key="center_message"

android:title="@string/center_message"

android:summary="@string/center_message_summary"

android:persistent="true"

android:defaultValue="true"/>

<EditTextPreference

android:key="text_message"

android:title="@string/text_message"

android:summary="@string/text_message_summary"

android:defaultValue="@string/hello_world"

android:persistent="true"/>

</PreferenceCategory>

</PreferenceScreen>

Поддерживаемых настроек не так много, однако их достаточно для удовлетворения основных потребностей. Установив флаг «persistent», не придется кодировать сохранение и загрузку, так как достаточно прочитать необходимое значение из SharedPreferences:

SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);

boolean bCenter = settings.getBoolean("center_message", true);

Дополнительными моментами являются зависимости android:dependency, которые позволяют «включать» нужные пункты тогда, когда отмечен «ведущий» элемент, а также дают возможность просто работать с вложенными наборами – они в приложении имеют вид отдельных окон. Для окна настроек нужно создать собственный класс-наследник PreferenceActivity. Наш .xml-прототип считывается в его конструкторе:

addPreferencesFromResource(R.xml.settings);

PreferenceActivity не очень хорошо поддается стилизации. Для соответствующего тега в AndroidManifest.xml можно добавить:

android:theme="@android:style/Theme.Light"

Но выйдет «каша» для вложенных настроек. Так что лучше всего оставить всё «as is», то есть – на черном фоне.

Теперь несколько слов о Nine-patch graphics. Это стандартный метод, который позволяет сделать графику в Android-приложении независимой от размера и разрешающей способности дисплея. По своей сути это не что иное, как обычное изображение в .png-формате, которое имеет однопиксельную служебную рамку. В состав Android SDK входит утилита draw9patch, которая специально предназначена для работы с этой самой рамкой. Черной однопиксельной линией сверху и слева отмечается область, которая будет дублирована при увеличении изображения. Линии же справа и снизу определяют, соответственно, «рабочую область» — место для текста, например.

Мы подготовим три 9patch-изображения: для обычной кнопки, нажатого её состояния и кнопки, находящейся в фокусе. Таким образом, мы сделаем кнопку в нашем приложении AdvancedHelloWorld нестандартной. Это не слишком разнообразное, даже скорее нудное занятие, однако оно открывает весьма немалые возможности. Что важно – все изображения 9patch обязательно должны иметь расширение вида «.9.png», в противном случае наше приложение не будет знать, что указанное изображение можно масштабировать согласно правилам 9patch. Соответственно, в папке ресурсов не может находиться два файла с одинаковым именем и расширениями .9.png и .png, иначе возникнут конфликты.