Введение в разработку приложений для ОС Android

Основы разработки интерфейсов мобильных приложений

Разбить на страницы
Показывать лекцию целиком

Цель лабораторной работы:

Изучение основ разработки интерфейсов мобильных приложений

Задачи лабораторной работы:

  • Изучить элементы интерфейса
  • Практическим путём научиться размещать элементы и менять их свойства
  • Разработать прототип интерфейса собственного приложения
  • 6.1 Введение

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

    Более подробную информацию о разработке интерфейсов мобильных приложений под Android можно узнать на сайте Design [Android Developers].

    6.2 Создание прототипа интерфейса

    Рассмотрим пример разработки интерфейса приложения, которое ищет в сети Интернет изображения по запросу пользователя, позволяет оценивать их, скачивать, и посещать интернет-страницы сайтов, на которых было найдено изображение.

    6.2.1 Создание заготовки для приложения

    Выглядеть главное окно будет примерно так:

    (рис 6.1) Интерфейс главной активности

    На нём присутствуют поле ввода текста для запроса пользователя и кнопка, начинающая поиск изображений. Внизу экрана две кнопки: "like" и "dislike", с их помощью пользователь сможет оценить изображение. После того, как пользователь сделает оценку изображения, текущее изображение закрывается и загружается следующее.

    Итак, начнём с создания нового проекта. Назовём его "RatingImages" ("Рейтинг изображений").

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

    Создайте иконку на свой вкус.

    (рис 6.2) Создание иконки

    После создания проекта откройте activity_main.xml из каталога res/layout/.

    Когда вы откроете файл activity_main.xml, вы увидите графический редактор макета. Благодаря этому редактору создание интерфейсов стало ещё интереснее, поскольку добавить элемент на форму можно при помощи перетаскивания мышью, к тому же, благодаря графическому редактору, не обязательно запускать эмулятор, чтобы увидеть результат своих трудов.

    Теперь щелкните по вкладке activity_main.xml в нижней части экрана. Открылся XML-редактор кода. Этот способ редактирования стандартный, но все изменения, вносимые в этот документ, можно так же ощутить визуально, перейдя на графический редактор.

    Вернёмся на вкладку с графическим редактором. Во-первых, подготовим документ к началу работы, для этого удалите <TextView>.

    Результат выглядит так:

    (рис 6.3) Проект, готовый к началу разработки

    На рабочей области экрана остался один элемент. Это макет <RelativeLayout>. В нём позиция дочерних элементов может быть описана по отношению друг к другу или к родителю. Подробнее о макетах можно узнать здесь.

    Два атрибута, ширина и высота (android:layout_width и android:layout_height), требуются для всех элементов для того, чтобы указать их размер.

    Так как <RelativeLayout> - это корень в макете, то нужно, чтобы он заполнял всю область экрана. Это достигается при помощи установки параметра "match_parent" для ширины и высоты. Это значение указывает, что ширина и высота элемента будет равна ширине и высоте родителя.

    (рис 6.4) Свойства <RelativeLayout> элемента

    Как установить это значение? Будем разбираться.

    Однократным щелчком левой кнопкой мыши по надписи "Width" активируйте строку с параметрами ширины:

    (рис 6.5) Свойства <RelativeLayout> элемента, выбран атрибут android:layout_width

    Щелчком левой кнопки мыши по области ввода вызовите диалоговое окно, и двойным щелчком сделайте выбор параметра:

    (рис 6.6) Свойства <RelativeLayout> элемента, выбран параметр "match_parent"

    Или щелчком правой кнопки мыши по <RelativeLayout> в Outline:

    (рис 6.7) Контекстное меню <RelativeLayout> элемента

    При выполнении первого способа вы увидели еще два возможных параметра: "fill_parent" и "wrap_content".

    На самом деле, match_parent = fill_parent, но "fill_parent" считается устаревшим, и к использованию в новых проектах предлагается "match_parent".

    Параметр "wrap_content" указывает, что представление будет увеличиваться при необходимости, чтобы поддерживать соответствие содержанию экрана.

    6.2.2 Добавление текстового поля

    Для начала добавьте элемент <LinearLayout> с горизонтальной ориентацией в <RelativeLayout>, и укажите для ширины и высоты параметр "wrap_content". Теперь, для создания пользовательского редактируемого текстового поля, добавьте элемент <EditText> с параметром "wrap_content" для ширины и высоты в <LinearLayout>.

    Сейчас должно получиться примерно следующее:

    (рис 6.8) Добавление текстового поля

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

    Теперь переходим к настройке добавленных нами элементов.

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

    Откроем редактор кода XML-файла и обратим внимание на элемент

    <EditText>:
    	<EditText
    		android:id="@+id/editText1"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content">
    		<requestFocus/> 
    	</EditText>
            

    Строка <requestFocus/> появляется добавлением элемента requestFocus (папка Advanced), и позволяет установить фокус на нужном компоненте. Важно использовать этот элемент, когда у вас имеется, к примеру, три текстовых поля, и нужно, чтобы фокус был на втором из них.

    При указании id, знак (@) требуется в том случае, если вы имеете в виду любой ресурс объекта из XML-файла. За ним следуют тип ресурса (в данном случае ID), косая черта (слеш) и имя ресурса (editText1).

    Знак плюс (+) перед типом ресурсов необходим только тогда, когда вы впервые определяете идентификатор ресурса.

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

    Зададим id для текстового поля. Для этого прямо в коде строку android:id="@+id/editText1" заменяем на android:id="@+id/edit_message", жмём CTRL+S и открываем графический редактор. Если всё хорошо, то в свойствах текстового поля в графе id будет следующее:

    (рис 6.9) Идентификатор текстового поля

    Добавим в код ещё две строки:

    android:ems="10" - задает соответствия для симметричного отображения шрифтов,

    android:hint="@string/edit_message" - содержание тестового поля "по умолчанию", т.е. пока пользователь не начал вводить в поле текст. Вместо того, чтобы использовать просто слово (например android:hint="message"), что крайне не удобно при изменении основного языка приложения, используется ссылка на значение, хранящееся в файле strings.xml. Поскольку это относится к конкретному ресурсу (а не только к id), знак плюс не нужен.

    Однако, мы ещё не определили строку ресурсов файле strings.xml, и потому вы получите следующее:

    (рис 6.10) Предупреждение: не найден ресурс, на который прописана ссылка

    Для того, чтобы ссылка на ресурс начала работать, нужно этот ресурс создать.

    Откройте файл res/values/strings.xml. Очевидно, что его тоже можно редактировать двумя способами: графически и вручную.

    Выбирайте тот способ, который больше по душе.

    (рис 6.11) Редактирование файла ресурсов графическим способом; добавление нового ресурса (рис 6.12) Редактирование файла ресурсов графическим способом; выбор типа ресурса, выбран тип String

    Заполняем поля "Имя" и "Значение":

    (рис 6.13) Редактирование файла ресурсов графическим способом

    Сохраняем и любуемся результатом:

    (рис 6.14) Отображение текста "По умолчанию" в поле ввода

    Подробнее о ресурсах - здесь.

    Аналогично создадим id для <LinearLayout>

    android:id="@+id/linear1"
            

    Сохраните изменения.

    6.2.3 Добавление кнопки

    Теперь добавьте <Button> в макет после элемента <EditText>:

    (рис 6.15) Новая кнопка

    Чтобы кнопка трансформировалась в соответствии с текстом кнопки, ширина и высота должны быть установлены во "wrap_content".

    Теперь поменяем надпись на кнопке на "Go!" с помощью ссылки на ресурс в XML-коде главной активности и добавления одного ресурса в файл strings.xml:

    (рис 6.16) Редактор XML-кода файла strings.xml

    Сохраните.

    На графическом редакторе главной активности будут изменения:

    (рис 6.17) Кнопка приняла новую форму, в соответствии с надписью на ней

    Теперь, когда мы поместили два главных представления на <LinearLayout> элемент, настало время добавить ещё два параметра для этого элемента.

    Речь идет о "приращении" правого и левого краёв лейаута к правому и левому краям <RelativeLayout> элемента соответственно. А сделать это проще простого - просто потяните мышкой один край к другому!

    (рис 6.18) "Приращение" правого края

    Зелёные стрелки по краям дают понять, к какому элементу удалось прицепить край:

    (рис 6.19) <LinearLayout> после выравнивания

    И, конечно, это отобразится в свойствах:

    (рис 6.20) Свойства <LinearLayout>

    6.2.4 Смена фона

    Идём дальше - попробуем поменять фон.

    Чтобы изменить цвет фона на чёрный, нужно в XML-коде главной активности написать одну строку в блоке <RelativeLayout> элемента:

    android:background="#000000".
            

    Сохраните и проверьте результат, открыв графический редактор.

    (рис 6.21) Фон стал чёрным

    Красиво, но скучно. Как сделать фон ещё интереснее? Поместить на него рисунок!

    Для этого сначала в папке res/ создадим папку drawable/

    (рис 6.22) Создание папки (рис 6.23) Создание папки: имя папки

    После того, как папка создана, нужно положить в эту папку изображение - картинка называется got.png:

    (рис 6.24) Изображение в папке drawable/

    После этого в папке drawable/ нужно создать файл background.xml, важно при создании выбрать параметр bitmap.

    (рис 6.25) Создание нового XML-файла (рис 6.26) Создание нового XML-файла

    Как только новый файл открылся, пропишем в него одну строчку, с указанием на то, откуда и какой файл использовать:

    <?xml version="1.0" encoding="utf-8"?>
    <bitmap	xmlns:android="http://schemas.android.com/apk/res/android" 
    	android:src="@drawable/got">
    </bitmap>
            

    Вернемся в редактор XML-кода, туда, где прописывали цвет фона.

    Вместо строки android:background="#000000" напишем ссылку на XML-файл android:background="@drawable/background".

    Сохраняем и видим результат:

    (рис 6.27) Новый фон

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

    Когда вы выбрали узор и скачали его, скопируйте изображение в папку drawable/.

    (рис 6.28) Копирование изображения (рис 6.29) Скопированное изображение

    Теперь немного изменим файл background.xml.

    Во-первых, нужно изменить имя изображение со старого на новое.

    android:src="@drawable/starring"
            

    Во-вторых, добавим такую строчку:

    android:tileMode="repeat" 
            

    Сохраняем.

    Атрибут android:tileMode задает тип заполнения, в данном случае простое повторение исходного изображения. Кроме repeat возможны варианты clamp и mirror. Помните, что данный приём применим только к bitmap, к фигурам, созданным при помощи XML, применить данную операцию нельзя.

    (рис 6.30) Варианты заполнения

    Настало время посмотреть, что из этого получилось:

    (рис 6.31) Фон из звездочек

    В <RelativeLayout> стоит добавлять android:background только в том случае, если вы хотите неподвижный фон, а в <ScrollView> чтобы фон прокручивался вместе с контентом.

    Если вы выбрали тёмный фон, то стоит поменять цвет текста, вводимого в поле ввода, например на белый.

    Для этого в блок <EditText> добавим строчку

    android:textColor="#ffffff"
            

    6.2.5 Область просмотра изображений

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

    Добавьте "рамку" <FrameLayout> в <RelativeLayout>:

    (рис 6.32) Добавление "рамки"

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

    Укажем этому элементу ширину, высоту и id. Предупреждение должно пропасть.

    (рис 6.33) Свойства "рамки"

    Сейчас FrameLayout "заезжает" на поле ввода и кнопку. Чтобы исправить это, нужно задать для "рамки" параметр, который будет следить, чтобы "рамка" находилась ниже, чем поле ввода и кнопка.

    Выберите из списка Outline "рамку" и кликом правой кнопки мыши вызовите контекстное меню: Other Properties -> Layout Parametrs -> Layout Below…

    (рис 6.34) Контекстное меню "рамки"

    Появится окно. В нём выбираем из списка "ID" имя лейаута, на котором находятся поле ввода и кнопка:

    (рис 6.35) Выбор элемента, ниже которого должна быть "рамка"

    Жмём ОК и "рамка" примет вид:

    (рис 6.36) Новое расположение "рамки"

    Теперь для наглядности поместим туда изображение.

    Сначала поместим само изображение в папку res/drawable/ и обновим её.

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

    (рис 6.37) Обновление папки

    Теперь поместим внутрь "рамки" <ImageView>

    (рис 6.38) Перемещение <ImageView>

    В появившемся окне выбираем нужное нам изображение и жмём OK

    (рис 6.39) Выбор файла

    Изображение должно появится на активности:

    (рис 6.40) Визуализация изображения

    Вместе с изображением появился новый предупреждающий знак.

    В описании предупреждения сказано: "[Accessibility] Missing contentDescription attribute on image". Давайте разберёмся, что это означает.

    Атрибут android:contentDescription используется в программах, которые поддерживают специальные возможности для людей с нарушениями зрения и слуха. То есть, текст, прописанный в этом атрибуте, не будет показан на экране, но при включенной в "Специальных возможностях" услуге "звуковые подсказки" этот текст будет проговариваться, когда пользователь переходит к этому элементу управления.

    Этот атрибут можно задать для ImageButton, ImageView и CheckBox, и задавать его или нет - дело каждого.

    Свойства у изображения должны быть следующими:

    (рис 6.41) Свойства изображения

    6.2.6 Кнопки "like" и "dislike"

    Пришло время создать кнопки оценивания.

    Для этого добавьте на форму <RelativeLayout>, задайте для него ширину и высоту wrap_content, и укажите id.

    Снова в папку res/drawable/ нужно добавить файлы. Найдите изображения "Палец вверх" и "Палец вниз", и поместите их в эту папку, после чего обновите её.

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

    Добавьте <ImageButton>, выберите изображение "Палец вверх", и переместите <RelativeLayout> в такое положение:

    (рис 6.42) Новая кнопка

    Укажите "рамке" быть выше, чем поле с кнопкой оценки:

    (рис 6.43) Контекстное меню "рамки" (рис 6.44) Выбор элемента, выше которого должна быть "рамка"

    В результате должно получиться следующее:

    (рис 6.45) Новое расположение элементов

    Добавьте еще одну кнопку - кнопку "Палец вниз". Она "наложилась" на первую кнопку. Чтобы это исправить, проделайте с <RelativeLayout> то же самое, что и с <LinearLayout>: растяните элемент влево и вправо, до получения такого результата:

    (рис 6.46) Выравнивание области с кнопками

    Теперь расставьте кнопки по краям так, чтобы они "прикрепились" к краям.

    (рис 6.47) Выравнивание кнопок

    Готово! Теперь можно запустить эмулятор и посмотреть, что получилось.

    (рис 6.48) Главная активность

    6.2.7 Листинги

    1)

    <RelativeLayout 	xmlns:android="http://schemas.android.com/apk/res/android"
    	xmlns:tools="http://schemas.android.com/tools"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent"
    	android:paddingBottom="@dimen/activity_vertical_margin"
    	android:paddingLeft="@dimen/activity_horizontal_margin"
    	android:paddingRight="@dimen/activity_horizontal_margin"
    	android:paddingTop="@dimen/activity_vertical_margin"
    	tools:context=".MainActivity" 
    	android:background="@drawable/background">
    
    	<LinearLayout
    		android:id="@+id/linear1"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:layout_alignParentLeft="true"
    		android:layout_alignParentRight="true"
    		android:orientation="horizontal" >
    		<EditText
    			android:id="@+id/edit_message"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:ems="10"
    			android:hint="@string/edit_message"
    			android:textColor="#ffffff" >
    			<requestFocus />
    		</EditText>
    
    		<Button
    			android:id="@+id/button1"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:text="@string/button_send" 
    		/>
    	</LinearLayout>
    
    	<FrameLayout
    		android:id="@+id/imgview"
    		android:layout_width="match_parent"
    		android:layout_height="match_parent"
    		android:layout_above="@+id/relative2"
    		android:layout_below="@id/linear1" >
    		<ImageView
    			android:id="@+id/puppy"
    			android:layout_width="wrap_content"
    			android:layout_height="match_parent"
    			android:src="@drawable/puppy" 
    		/>
    	</FrameLayout>
    
    	<RelativeLayout
    		android:id="@+id/relative2"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:layout_alignLeft="@+id/imgview"
    		android:layout_alignParentBottom="true"
    		android:layout_alignRight="@+id/imgview" >
    		<ImageButton
    			android:id="@+id/imageButton2"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:layout_alignParentRight="true"
    			android:layout_alignParentTop="true"
    			android:src="@drawable/dislike" 
    		/>
    		<ImageButton
    			android:id="@+id/imageButton1"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:layout_alignParentLeft="true"
    			android:layout_alignParentTop="true"
    			android:src="@drawable/like" 
    		/>
    	</RelativeLayout>
    
    </RelativeLayout>
            

    2)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
    		<string name="app_name">RatingImages</string>
    		<string name="action_settings">Settings</string>
    		<string name="hello_world">Hello world!</string>
    		<string name="edit_message">Enter your text here</string>
    		<string name="button_send">Go!</string>
    
    </resources> 
            

    3)

    <?xml version="1.0" encoding="utf-8"?>
    
    <bitmap
    	xmlns:android="http://schemas.android.com/apk/res/android" 
    	android:src="@drawable/starring"
    	android:tileMode="repeat" >
    
    </bitmap>
            

    6.3 BuildingBlocks или элементы для построения интерфейса

    Среда разработки "AndroidIDE" открывает широкий выбор готовых к использованию элементов для создания выдающихся приложений.

    Кнопка (Button) состоит из текста и/или изображения, которые дают понять пользователю, что произойдёт, если нажать на эту кнопку. Важно помнить, что человек по своей природе привык взаимодействовать с объектами, поэтому фон у кнопки абсолютно не обязателен.

    (рис 6.49a) Кнопка-изображение (рис 6.49b) Кнопка-текст

    Текстовые поля (TextFields)

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

    (рис 6.50) 50 Текстовые поля, поиск контактов (рис 6.51) Выделение текста

    Ползунки и слайдеры (Seek Bars and Sliders)

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

    (рис 6.52) Ползунки в светлой и темной темах

    Интерактивный характер слайдера делает его удобным для настроек, которые отражают уровни интенсивности, такие как громкость, яркость, или насыщенность цвета.

    Так, например, уровень громкости можно регулировать кнопками на корпусе устройства или при помощи жеста пальцем по экрану.

    (рис 6.53) Настройка звука

    Прогресс-бары и активности (ProgressActivity)

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

    (рис 6.54) Процесс загрузки приложения

    Переключатели (Switches) позволяют пользователю выбирать параметры.

    Есть три вида переключателей: флажки, радио-кнопки, и включение/выключение выключателей.

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

    (рис 6.55) Флажки

    Радио-кнопки позволяют выбрать только один вариант из списка. Радио-кнопки формируются в группы.

    (рис 6.56) Радио-кнопки

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

    (рис 6.57) Выключатели

    Диалоговые окна (Dialogs) помогают приложению взаимодействовать с пользователем. Это может быть как банальный вопрос с двумя вариантами ответа (OK и Отмена), так и сложные окна с множеством настраиваемых пользователем параметров.

    (рис 6.58) Примеры диалоговых окон

    Средство выбора (Pickers) - это простой способ выбрать одно значение из набора путём последовательного перебора. Удобный перебор предлагаемых значений при помощи клика по стрелочкам или прокрутки, так же можно ввести значение с клавиатуры.

    (рис 6.59) Примеры пикеров

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

    Для того чтобы индикатор прокрутки не занимал место у рабочей области экрана, после приостановки пользования прокруткой, индикатор исчезает, и появляется снова, стоит только начать "прокручивать" пальцем. Для удобства поиска чего-либо в алфавитном списке, рядом с индикатором прокрутки возникает индекс с указанием на то, в каком разделе находится индикатор.

    (рис 6.60) Индикатор и индекс прокрутки

    Выпадающий список (Spinner) обеспечивает удобный способ выбора одного значения из набора.

    (рис 6.61) Спиннер для выбора типа e-mail адреса

    Вкладки (Tabs) позволяют легко просматривать и переключаться между различными окнами или функциональными элементами приложения. Вкладки, прокручиваемые движением пальца (ScrollableTabs), делают этот процесс еще прощё и приятнее.

    Основные вкладки (FixedTabs) удобны при отображении трех и менее вкладок, поскольку ширина вкладок фиксируется по самому длинному названию вкладки.

    (рис 6.62) Вкладки

    Списки (Lists) удобны для представления нескольких позиций информации в вертикальном расположении.

    (рис 6.63) Список

    Сетки (GridLists) - это альтернатива стандартного списка. С помощью сетки можно создавать более удобное представление образных данных, нежели с помощью списка. Ещё одним плюсом сетки является то, что прокрутку можно осуществлять не только в вертикальном, но и в горизонтальном направлении.

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

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

    (рис 6.64) Сетка с альбомами

    Задание

  • Создайте в приложении на главной активности строку, в которой будет выводиться адрес сайта, откуда загружено изображение, и кнопку для перехода на этот сайт.
  • Подумайте над интерфейсом собственного приложения. Какие элементы управления оно может содержать? Попробуйте воплотить его интерфейс на практике.
  • Страницы:

    Цель лабораторной работы:

    Изучение основ разработки интерфейсов мобильных приложений

    Задачи лабораторной работы:

  • Изучить элементы интерфейса
  • Практическим путём научиться размещать элементы и менять их свойства
  • Разработать прототип интерфейса собственного приложения
  • 6.1 Введение

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

    Более подробную информацию о разработке интерфейсов мобильных приложений под Android можно узнать на сайте Design [Android Developers].

    6.2 Создание прототипа интерфейса

    Рассмотрим пример разработки интерфейса приложения, которое ищет в сети Интернет изображения по запросу пользователя, позволяет оценивать их, скачивать, и посещать интернет-страницы сайтов, на которых было найдено изображение.

    6.2.1 Создание заготовки для приложения

    Выглядеть главное окно будет примерно так:

    (рис 6.1) Интерфейс главной активности

    На нём присутствуют поле ввода текста для запроса пользователя и кнопка, начинающая поиск изображений. Внизу экрана две кнопки: "like" и "dislike", с их помощью пользователь сможет оценить изображение. После того, как пользователь сделает оценку изображения, текущее изображение закрывается и загружается следующее.

    Итак, начнём с создания нового проекта. Назовём его "RatingImages" ("Рейтинг изображений").

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

    Создайте иконку на свой вкус.

    (рис 6.2) Создание иконки

    После создания проекта откройте activity_main.xml из каталога res/layout/.

    Когда вы откроете файл activity_main.xml, вы увидите графический редактор макета. Благодаря этому редактору создание интерфейсов стало ещё интереснее, поскольку добавить элемент на форму можно при помощи перетаскивания мышью, к тому же, благодаря графическому редактору, не обязательно запускать эмулятор, чтобы увидеть результат своих трудов.

    Теперь щелкните по вкладке activity_main.xml в нижней части экрана. Открылся XML-редактор кода. Этот способ редактирования стандартный, но все изменения, вносимые в этот документ, можно так же ощутить визуально, перейдя на графический редактор.

    Вернёмся на вкладку с графическим редактором. Во-первых, подготовим документ к началу работы, для этого удалите <TextView>.

    Результат выглядит так:

    (рис 6.3) Проект, готовый к началу разработки

    На рабочей области экрана остался один элемент. Это макет <RelativeLayout>. В нём позиция дочерних элементов может быть описана по отношению друг к другу или к родителю. Подробнее о макетах можно узнать здесь.

    Два атрибута, ширина и высота (android:layout_width и android:layout_height), требуются для всех элементов для того, чтобы указать их размер.

    Так как <RelativeLayout> - это корень в макете, то нужно, чтобы он заполнял всю область экрана. Это достигается при помощи установки параметра "match_parent" для ширины и высоты. Это значение указывает, что ширина и высота элемента будет равна ширине и высоте родителя.

    (рис 6.4) Свойства <RelativeLayout> элемента

    Как установить это значение? Будем разбираться.

    Однократным щелчком левой кнопкой мыши по надписи "Width" активируйте строку с параметрами ширины:

    (рис 6.5) Свойства <RelativeLayout> элемента, выбран атрибут android:layout_width

    Щелчком левой кнопки мыши по области ввода вызовите диалоговое окно, и двойным щелчком сделайте выбор параметра:

    (рис 6.6) Свойства <RelativeLayout> элемента, выбран параметр "match_parent"

    Или щелчком правой кнопки мыши по <RelativeLayout> в Outline:

    (рис 6.7) Контекстное меню <RelativeLayout> элемента

    При выполнении первого способа вы увидели еще два возможных параметра: "fill_parent" и "wrap_content".

    На самом деле, match_parent = fill_parent, но "fill_parent" считается устаревшим, и к использованию в новых проектах предлагается "match_parent".

    Параметр "wrap_content" указывает, что представление будет увеличиваться при необходимости, чтобы поддерживать соответствие содержанию экрана.

    6.2.2 Добавление текстового поля

    Для начала добавьте элемент <LinearLayout> с горизонтальной ориентацией в <RelativeLayout>, и укажите для ширины и высоты параметр "wrap_content". Теперь, для создания пользовательского редактируемого текстового поля, добавьте элемент <EditText> с параметром "wrap_content" для ширины и высоты в <LinearLayout>.

    Сейчас должно получиться примерно следующее:

    (рис 6.8) Добавление текстового поля

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

    Теперь переходим к настройке добавленных нами элементов.

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

    Откроем редактор кода XML-файла и обратим внимание на элемент

    <EditText>:
    	<EditText
    		android:id="@+id/editText1"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content">
    		<requestFocus/> 
    	</EditText>
            

    Строка <requestFocus/> появляется добавлением элемента requestFocus (папка Advanced), и позволяет установить фокус на нужном компоненте. Важно использовать этот элемент, когда у вас имеется, к примеру, три текстовых поля, и нужно, чтобы фокус был на втором из них.

    При указании id, знак (@) требуется в том случае, если вы имеете в виду любой ресурс объекта из XML-файла. За ним следуют тип ресурса (в данном случае ID), косая черта (слеш) и имя ресурса (editText1).

    Знак плюс (+) перед типом ресурсов необходим только тогда, когда вы впервые определяете идентификатор ресурса.

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

    Зададим id для текстового поля. Для этого прямо в коде строку android:id="@+id/editText1" заменяем на android:id="@+id/edit_message", жмём CTRL+S и открываем графический редактор. Если всё хорошо, то в свойствах текстового поля в графе id будет следующее:

    (рис 6.9) Идентификатор текстового поля

    Добавим в код ещё две строки:

    android:ems="10" - задает соответствия для симметричного отображения шрифтов,

    android:hint="@string/edit_message" - содержание тестового поля "по умолчанию", т.е. пока пользователь не начал вводить в поле текст. Вместо того, чтобы использовать просто слово (например android:hint="message"), что крайне не удобно при изменении основного языка приложения, используется ссылка на значение, хранящееся в файле strings.xml. Поскольку это относится к конкретному ресурсу (а не только к id), знак плюс не нужен.

    Однако, мы ещё не определили строку ресурсов файле strings.xml, и потому вы получите следующее:

    (рис 6.10) Предупреждение: не найден ресурс, на который прописана ссылка

    Для того, чтобы ссылка на ресурс начала работать, нужно этот ресурс создать.

    Откройте файл res/values/strings.xml. Очевидно, что его тоже можно редактировать двумя способами: графически и вручную.

    Выбирайте тот способ, который больше по душе.

    (рис 6.11) Редактирование файла ресурсов графическим способом; добавление нового ресурса (рис 6.12) Редактирование файла ресурсов графическим способом; выбор типа ресурса, выбран тип String

    Заполняем поля "Имя" и "Значение":

    (рис 6.13) Редактирование файла ресурсов графическим способом

    Сохраняем и любуемся результатом:

    (рис 6.14) Отображение текста "По умолчанию" в поле ввода

    Подробнее о ресурсах - здесь.

    Аналогично создадим id для <LinearLayout>

    android:id="@+id/linear1"
            

    Сохраните изменения.

    6.2.3 Добавление кнопки

    Теперь добавьте <Button> в макет после элемента <EditText>:

    (рис 6.15) Новая кнопка

    Чтобы кнопка трансформировалась в соответствии с текстом кнопки, ширина и высота должны быть установлены во "wrap_content".

    Теперь поменяем надпись на кнопке на "Go!" с помощью ссылки на ресурс в XML-коде главной активности и добавления одного ресурса в файл strings.xml:

    (рис 6.16) Редактор XML-кода файла strings.xml

    Сохраните.

    На графическом редакторе главной активности будут изменения:

    (рис 6.17) Кнопка приняла новую форму, в соответствии с надписью на ней

    Теперь, когда мы поместили два главных представления на <LinearLayout> элемент, настало время добавить ещё два параметра для этого элемента.

    Речь идет о "приращении" правого и левого краёв лейаута к правому и левому краям <RelativeLayout> элемента соответственно. А сделать это проще простого - просто потяните мышкой один край к другому!

    (рис 6.18) "Приращение" правого края

    Зелёные стрелки по краям дают понять, к какому элементу удалось прицепить край:

    (рис 6.19) <LinearLayout> после выравнивания

    И, конечно, это отобразится в свойствах:

    (рис 6.20) Свойства <LinearLayout>

    6.2.4 Смена фона

    Идём дальше - попробуем поменять фон.

    Чтобы изменить цвет фона на чёрный, нужно в XML-коде главной активности написать одну строку в блоке <RelativeLayout> элемента:

    android:background="#000000".
            

    Сохраните и проверьте результат, открыв графический редактор.

    (рис 6.21) Фон стал чёрным

    Красиво, но скучно. Как сделать фон ещё интереснее? Поместить на него рисунок!

    Для этого сначала в папке res/ создадим папку drawable/

    (рис 6.22) Создание папки (рис 6.23) Создание папки: имя папки

    После того, как папка создана, нужно положить в эту папку изображение - картинка называется got.png:

    (рис 6.24) Изображение в папке drawable/

    После этого в папке drawable/ нужно создать файл background.xml, важно при создании выбрать параметр bitmap.

    (рис 6.25) Создание нового XML-файла (рис 6.26) Создание нового XML-файла

    Как только новый файл открылся, пропишем в него одну строчку, с указанием на то, откуда и какой файл использовать:

    <?xml version="1.0" encoding="utf-8"?>
    <bitmap	xmlns:android="http://schemas.android.com/apk/res/android" 
    	android:src="@drawable/got">
    </bitmap>
            

    Вернемся в редактор XML-кода, туда, где прописывали цвет фона.

    Вместо строки android:background="#000000" напишем ссылку на XML-файл android:background="@drawable/background".

    Сохраняем и видим результат:

    (рис 6.27) Новый фон

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

    Когда вы выбрали узор и скачали его, скопируйте изображение в папку drawable/.

    (рис 6.28) Копирование изображения (рис 6.29) Скопированное изображение

    Теперь немного изменим файл background.xml.

    Во-первых, нужно изменить имя изображение со старого на новое.

    android:src="@drawable/starring"
            

    Во-вторых, добавим такую строчку:

    android:tileMode="repeat" 
            

    Сохраняем.

    Атрибут android:tileMode задает тип заполнения, в данном случае простое повторение исходного изображения. Кроме repeat возможны варианты clamp и mirror. Помните, что данный приём применим только к bitmap, к фигурам, созданным при помощи XML, применить данную операцию нельзя.

    (рис 6.30) Варианты заполнения

    Настало время посмотреть, что из этого получилось:

    (рис 6.31) Фон из звездочек

    В <RelativeLayout> стоит добавлять android:background только в том случае, если вы хотите неподвижный фон, а в <ScrollView> чтобы фон прокручивался вместе с контентом.

    Если вы выбрали тёмный фон, то стоит поменять цвет текста, вводимого в поле ввода, например на белый.

    Для этого в блок <EditText> добавим строчку

    android:textColor="#ffffff"
            

    6.2.5 Область просмотра изображений

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

    Добавьте "рамку" <FrameLayout> в <RelativeLayout>:

    (рис 6.32) Добавление "рамки"

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

    Укажем этому элементу ширину, высоту и id. Предупреждение должно пропасть.

    (рис 6.33) Свойства "рамки"

    Сейчас FrameLayout "заезжает" на поле ввода и кнопку. Чтобы исправить это, нужно задать для "рамки" параметр, который будет следить, чтобы "рамка" находилась ниже, чем поле ввода и кнопка.

    Выберите из списка Outline "рамку" и кликом правой кнопки мыши вызовите контекстное меню: Other Properties -> Layout Parametrs -> Layout Below…

    (рис 6.34) Контекстное меню "рамки"

    Появится окно. В нём выбираем из списка "ID" имя лейаута, на котором находятся поле ввода и кнопка:

    (рис 6.35) Выбор элемента, ниже которого должна быть "рамка"

    Жмём ОК и "рамка" примет вид:

    (рис 6.36) Новое расположение "рамки"

    Теперь для наглядности поместим туда изображение.

    Сначала поместим само изображение в папку res/drawable/ и обновим её.

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

    (рис 6.37) Обновление папки

    Теперь поместим внутрь "рамки" <ImageView>

    (рис 6.38) Перемещение <ImageView>

    В появившемся окне выбираем нужное нам изображение и жмём OK

    (рис 6.39) Выбор файла

    Изображение должно появится на активности:

    (рис 6.40) Визуализация изображения

    Вместе с изображением появился новый предупреждающий знак.

    В описании предупреждения сказано: "[Accessibility] Missing contentDescription attribute on image". Давайте разберёмся, что это означает.

    Атрибут android:contentDescription используется в программах, которые поддерживают специальные возможности для людей с нарушениями зрения и слуха. То есть, текст, прописанный в этом атрибуте, не будет показан на экране, но при включенной в "Специальных возможностях" услуге "звуковые подсказки" этот текст будет проговариваться, когда пользователь переходит к этому элементу управления.

    Этот атрибут можно задать для ImageButton, ImageView и CheckBox, и задавать его или нет - дело каждого.

    Свойства у изображения должны быть следующими:

    (рис 6.41) Свойства изображения

    6.2.6 Кнопки "like" и "dislike"

    Пришло время создать кнопки оценивания.

    Для этого добавьте на форму <RelativeLayout>, задайте для него ширину и высоту wrap_content, и укажите id.

    Снова в папку res/drawable/ нужно добавить файлы. Найдите изображения "Палец вверх" и "Палец вниз", и поместите их в эту папку, после чего обновите её.

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

    Добавьте <ImageButton>, выберите изображение "Палец вверх", и переместите <RelativeLayout> в такое положение:

    (рис 6.42) Новая кнопка

    Укажите "рамке" быть выше, чем поле с кнопкой оценки:

    (рис 6.43) Контекстное меню "рамки" (рис 6.44) Выбор элемента, выше которого должна быть "рамка"

    В результате должно получиться следующее:

    (рис 6.45) Новое расположение элементов

    Добавьте еще одну кнопку - кнопку "Палец вниз". Она "наложилась" на первую кнопку. Чтобы это исправить, проделайте с <RelativeLayout> то же самое, что и с <LinearLayout>: растяните элемент влево и вправо, до получения такого результата:

    (рис 6.46) Выравнивание области с кнопками

    Теперь расставьте кнопки по краям так, чтобы они "прикрепились" к краям.

    (рис 6.47) Выравнивание кнопок

    Готово! Теперь можно запустить эмулятор и посмотреть, что получилось.

    (рис 6.48) Главная активность

    6.2.7 Листинги

    1)

    <RelativeLayout 	xmlns:android="http://schemas.android.com/apk/res/android"
    	xmlns:tools="http://schemas.android.com/tools"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent"
    	android:paddingBottom="@dimen/activity_vertical_margin"
    	android:paddingLeft="@dimen/activity_horizontal_margin"
    	android:paddingRight="@dimen/activity_horizontal_margin"
    	android:paddingTop="@dimen/activity_vertical_margin"
    	tools:context=".MainActivity" 
    	android:background="@drawable/background">
    
    	<LinearLayout
    		android:id="@+id/linear1"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:layout_alignParentLeft="true"
    		android:layout_alignParentRight="true"
    		android:orientation="horizontal" >
    		<EditText
    			android:id="@+id/edit_message"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:ems="10"
    			android:hint="@string/edit_message"
    			android:textColor="#ffffff" >
    			<requestFocus />
    		</EditText>
    
    		<Button
    			android:id="@+id/button1"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:text="@string/button_send" 
    		/>
    	</LinearLayout>
    
    	<FrameLayout
    		android:id="@+id/imgview"
    		android:layout_width="match_parent"
    		android:layout_height="match_parent"
    		android:layout_above="@+id/relative2"
    		android:layout_below="@id/linear1" >
    		<ImageView
    			android:id="@+id/puppy"
    			android:layout_width="wrap_content"
    			android:layout_height="match_parent"
    			android:src="@drawable/puppy" 
    		/>
    	</FrameLayout>
    
    	<RelativeLayout
    		android:id="@+id/relative2"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:layout_alignLeft="@+id/imgview"
    		android:layout_alignParentBottom="true"
    		android:layout_alignRight="@+id/imgview" >
    		<ImageButton
    			android:id="@+id/imageButton2"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:layout_alignParentRight="true"
    			android:layout_alignParentTop="true"
    			android:src="@drawable/dislike" 
    		/>
    		<ImageButton
    			android:id="@+id/imageButton1"
    			android:layout_width="wrap_content"
    			android:layout_height="wrap_content"
    			android:layout_alignParentLeft="true"
    			android:layout_alignParentTop="true"
    			android:src="@drawable/like" 
    		/>
    	</RelativeLayout>
    
    </RelativeLayout>
            

    2)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
    		<string name="app_name">RatingImages</string>
    		<string name="action_settings">Settings</string>
    		<string name="hello_world">Hello world!</string>
    		<string name="edit_message">Enter your text here</string>
    		<string name="button_send">Go!</string>
    
    </resources> 
            

    3)

    <?xml version="1.0" encoding="utf-8"?>
    
    <bitmap
    	xmlns:android="http://schemas.android.com/apk/res/android" 
    	android:src="@drawable/starring"
    	android:tileMode="repeat" >
    
    </bitmap>
            

    6.3 BuildingBlocks или элементы для построения интерфейса

    Среда разработки "AndroidIDE" открывает широкий выбор готовых к использованию элементов для создания выдающихся приложений.

    Кнопка (Button) состоит из текста и/или изображения, которые дают понять пользователю, что произойдёт, если нажать на эту кнопку. Важно помнить, что человек по своей природе привык взаимодействовать с объектами, поэтому фон у кнопки абсолютно не обязателен.

    (рис 6.49a) Кнопка-изображение (рис 6.49b) Кнопка-текст

    Текстовые поля (TextFields)

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

    (рис 6.50) 50 Текстовые поля, поиск контактов (рис 6.51) Выделение текста

    Ползунки и слайдеры (Seek Bars and Sliders)

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

    (рис 6.52) Ползунки в светлой и темной темах

    Интерактивный характер слайдера делает его удобным для настроек, которые отражают уровни интенсивности, такие как громкость, яркость, или насыщенность цвета.

    Так, например, уровень громкости можно регулировать кнопками на корпусе устройства или при помощи жеста пальцем по экрану.

    (рис 6.53) Настройка звука

    Прогресс-бары и активности (ProgressActivity)

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

    (рис 6.54) Процесс загрузки приложения

    Переключатели (Switches) позволяют пользователю выбирать параметры.

    Есть три вида переключателей: флажки, радио-кнопки, и включение/выключение выключателей.

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

    (рис 6.55) Флажки

    Радио-кнопки позволяют выбрать только один вариант из списка. Радио-кнопки формируются в группы.

    (рис 6.56) Радио-кнопки

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

    (рис 6.57) Выключатели

    Диалоговые окна (Dialogs) помогают приложению взаимодействовать с пользователем. Это может быть как банальный вопрос с двумя вариантами ответа (OK и Отмена), так и сложные окна с множеством настраиваемых пользователем параметров.

    (рис 6.58) Примеры диалоговых окон

    Средство выбора (Pickers) - это простой способ выбрать одно значение из набора путём последовательного перебора. Удобный перебор предлагаемых значений при помощи клика по стрелочкам или прокрутки, так же можно ввести значение с клавиатуры.

    (рис 6.59) Примеры пикеров

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

    Для того чтобы индикатор прокрутки не занимал место у рабочей области экрана, после приостановки пользования прокруткой, индикатор исчезает, и появляется снова, стоит только начать "прокручивать" пальцем. Для удобства поиска чего-либо в алфавитном списке, рядом с индикатором прокрутки возникает индекс с указанием на то, в каком разделе находится индикатор.

    (рис 6.60) Индикатор и индекс прокрутки

    Выпадающий список (Spinner) обеспечивает удобный способ выбора одного значения из набора.

    (рис 6.61) Спиннер для выбора типа e-mail адреса

    Вкладки (Tabs) позволяют легко просматривать и переключаться между различными окнами или функциональными элементами приложения. Вкладки, прокручиваемые движением пальца (ScrollableTabs), делают этот процесс еще прощё и приятнее.

    Основные вкладки (FixedTabs) удобны при отображении трех и менее вкладок, поскольку ширина вкладок фиксируется по самому длинному названию вкладки.

    (рис 6.62) Вкладки

    Списки (Lists) удобны для представления нескольких позиций информации в вертикальном расположении.

    (рис 6.63) Список

    Сетки (GridLists) - это альтернатива стандартного списка. С помощью сетки можно создавать более удобное представление образных данных, нежели с помощью списка. Ещё одним плюсом сетки является то, что прокрутку можно осуществлять не только в вертикальном, но и в горизонтальном направлении.

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

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

    (рис 6.64) Сетка с альбомами

    Задание

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