Главная страница
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
qrcode

Программирование под Android. Для профессионалов


Скачать 19.35 Mb.
НазваниеПрограммирование под Android. Для профессионалов
АнкорBrayn Khardi Bill Fillips - Programmirovanie po.
Дата23.05.2017
Размер19.35 Mb.
Формат файлаpdf
Имя файлаBrayn_Khardi_Bill_Fillips_-_Programmirovanie_po.pdf
оригинальный pdf просмотр
ТипДокументы
#21061
страница17 из 55
КаталогОбразовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
1   ...   13   14   15   16   17   18   19   20   ...   55
Глава 8. Макеты и виджеты
«ритм 48dp». Полный список рекомендаций находится по адресу https://developer.
android.com/design/index.html
Современные приложения Android должны соответствовать этим рекоменда- циям, насколько это возможно. Рекомендации в значительной мере зависят от новой функциональности Android SDK, которая не всегда доступна или легко реализуема на старых устройствах. Некоторые рекомендации могут соблюдаться с использованием библиотеки поддержки, но для многих требуются библиотеки сторонних разработчиков — такие, как
ActionBarSherlock
, о которой можно про- читать в главе 16.
Параметры макета
Вероятно, вы уже заметили, что некоторые имена атрибутов начинаются с layout_
(
android:layout_marginLeft
), а у других атрибутов этого префикса нет
(
android:text
).
Атрибуты, имена которых не начинаются с layout_
, являются рекомендациями для виджетов. При заполнении виджет вызывает метод для настройки своей конфигу- рации на основании этих атрибутов и их значений.
Если имя атрибута начинается с layout_
, то этот атрибут является директивой для родителя этого виджета. Такие атрибуты, называемые параметрами макета, сообщают родительскому макету, как следует расположить дочерний элемент внутри родителя.
Даже если объект макета (например,
LinearLayout
) является корневым элементом, он все равно остается виджетом, имеющим родителя, и у него есть параметры макета.
Определяя элемент
LinearLayout в файле fragment_crime.xml
, мы задали атрибуты android:layout_width и android:layout_height
. Эти атрибуты будут использоваться родительским макетом
LinearLayout при заполнении. В данном случае параметры макета
LinearLayout будут использоваться элементом
FrameLayout в представлении содержимого
CrimeActivity
Поля и отступы
В файле fragment_crime.xml виджетам назначаются атрибуты margin и padding
. Начи- нающие разработчики иногда путают эти атрибуты, определяющие соответственно
поля
и отступы. Теперь, когда вы понимаете, что такое параметр макета, будет проще объяснить, чем они различаются. Атрибуты margin являются параметрами макета; они определяют расстояние между виджетами. Так как виджет располагает информацией только о самом себе, за соблюдение полей отвечает родитель виджета.
Напротив, отступ не является параметром макета. Атрибут android:padding сообща- ет виджету, с каким превышением размера содержимого он должен прорисовывать себя. Допустим, вы хотите заметно увеличить размеры кнопки даты без изменения размера текста. Добавьте в
Button следующий атрибут, сохраните макет и запустите приложение заново.

Использование графического конструктора
171
Листинг 8.8. Назначение отступов

172
Глава 8. Макеты и виджеты
Рис. 8.4. CrimeFragment в альбомной ориентации
Кнопка даты становится слишком длинной; было бы лучше, если бы в альбомной ориентации кнопка и флажок располагались рядом друг с другом. Для этого создайте каталог res/layout-land
(щелкните правой кнопкой мыши на каталоге res/
на панели
Package
Explorer и выберите команду
New

Folder
), после чего скопируйте файл frag- ment_crime.xml в res/layout-land/
Чтобы внести изменения в графическом конструкторе, сначала закройте файл res/
layout/fragment_crime.xml
, если он открыт в редакторе. Откройте файл res/layout-land/
fragment_crime.xml и выберите вкладку
Graphical
Layout
В середине графического конструктора макета в области предварительного про- смотра отображается уже знакомый альбомный макет. Слева находится палитра.
Панель содержит все необходимые виджеты, упорядоченные по категориям.
Предва- ритель- ный про- смотр
Свойства
Структура
Палитра
Рис. 8.5. Графический конструктор макета

Использование графического конструктора
173
Справа от области предварительного просмотра находится панель структуры. На ней показана иерархия виджетов в макете.
Под панелью структуры находится панель свойств. На ней можно просматривать и редактировать атрибуты виджета, выделенного на панели структуры.
Какие же изменения следует внести в этот макет? Взгляните на рис. 8.6.
Рис. 8.6. Альбомный макет для CrimeFragment
Изменения можно разделить на четыре группы:

Добавление виджета
LinearLayout в макет.

Редактирование атрибутов
LinearLayout

Назначение виджетов
Button и
CheckBox потомками
LinearLayout

Обновление параметров макета
Button и
CheckBox
Добавление нового виджета
Чтобы добавить виджет, можно выделить его в палитре и перетащить на панель структуры. Щелкните на категории
Layouts в палитре. Выберите пункт
LinearLayout
(Horizontal)
и перетащите на панель структуры. Отпустите перетаскиваемый объект
LinearLayout на коренном элементе
LinearLayout
, чтобы сделать его прямым по- томком корневого элемента
LinearLayout
Виджеты также можно добавлять перетаскиванием из палитры в область предва- рительного просмотра. Однако виджеты
Layout часто пусты или закрыты другими представлениями, поэтому может быть трудно понять, где следует разместить виджет в области предварительного просмотра для получения нужной иерархии.

174
Глава 8. Макеты и виджеты
Перетаскивание на панель структуры существенно упрощает выполнение этой операции.
Рис. 8.7. Добавление виджета LinearLayout в файл fragment_crime.xml
Редактирование атрибутов в свойствах
Выберите новый виджет
LinearLayout на панели структуры, чтобы отобразить его атрибуты на панели свойств. Разверните категорию
Layout
Parameters
, затем катего- рию
Margins
Мы хотим, чтобы поля нового виджета
Linear-
Layout совпадали с полями других виджетов.
Выделите поле рядом с
Left и введите значение
16dp
. Сделайте то же самое для правого (
Right
) поля.
(На некоторых платформах при попытке ввести данные в эти поля на экране появляется вре- менное окно. Это обходное решение известной ошибки… которое, к сожалению, не позволяет ввести значение. Если это произойдет, сохра- ните файл, переключитесь на разметку XML и скопируйте два атрибута margin из
EditText в
LinearLayout
).
Сохраните файл макета и переключитесь на раз- метку XML при помощи вкладки fragment_crime.
xml в нижней части области предварительного просмотра. Вы увидите только что добавленный элемент
LinearLayout с атрибу- тами полей.
Рис. 8.8. Назначение полей на панели свойств

Реорганизация виджетов на панели структуры
175
Реорганизация виджетов на панели структуры
Следующий шаг — назначение виджетов
Button и
CheckBox потомками нового виджета
LinearLayout
. Вернитесь к графическому конструктору, выберите на па- нели структуры виджет
Button и перетащите его на
LinearLayout
На панели структуры отражается тот факт, что
Button теперь является потомком нового вид- жета
LinearLayout
. Проделайте то же самое с
CheckBox
Если потомки размещаются не в том порядке, их можно переупорядочить посредством пере- таскивания. Также на панели структуры можно удалять виджеты из макета, но будьте осторож- ны: удаление виджета приводит к удалению его потомков.
В области предварительного просмотра виджет
CheckBox не виден — его скрывает
Button
. Вид- жет
LinearLayout проверил ширину (
match_par- ent
) своего первого потомка (
Button
) и выделил ему все пространство, ничего не оставив
Check-
Box
(рис. 8.10).
Рис. 8.10. Виджет Button, который был определен первым, скрывает CheckBox
Рис. 8.9. Виджеты Button и CheckBox теперь являются потомками LinearLayout

176
Глава 8. Макеты и виджеты
Чтобы восстановить равноправие потомков
LinearLayout
, мы изменим параметры макета потомков.
Обновление параметров макета потомков
Сначала выделите кнопку даты на панели структуры. На панели свойств щелкни- те на текущем значении
Width и замените его значением wrap_content
Удалите оба значения
16dp полей кнопки. Теперь, когда кнопка находится внутри
LinearLayout
, поля ей не нужны.
Найдите поле
Weight в разделе
Layout
Parameters и задайте ему значение 1. Это поле соответству- ет атрибуту android:layout_weight на рис. 8.6.
Выберите виджет
CheckBox на панели структуры и внесите те же изменения: атрибут
Width дол- жен содержать wrap_content
, атрибут
Weight
— 1, а атрибуты полей должны быть пустыми.
В области предварительного просмотра убе- дитесь в том, что оба виджета теперь видны.
Сохраните файл и вернитесь к XML, чтобы под- твердить изменения. В листинге 8.9 приведена соответствующая разметка XML.
Листинг 8.9. Разметка XML макета, созданного в графическом конструкторе
(layout-land/fragment_crime.xml)
android:layout_height="wrap_content"
android:text="@string/crime_details_label"
/>
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" >

Реорганизация виджетов на панели структуры
177
Как работает android:layout_weight
Атрибут веса android:layout_weight сообщает виджету
LinearLayout
, как он должен распределить потомков по размеру контейнера. Обоим виджетам заданы одина- ковые значения ширины, но это не гарантирует, что они будут иметь одинаковую ширину на экране. Для определения ширин дочерних представлений
LinearLayout использует комбинацию параметров layout_width и layout_weight
LinearLayout вычисляет ширину представления в два прохода. На первом проходе
LinearLayout проверяет значение layout_width
(или layout_height для вертикаль- ной ориентации). Значение layout_width как для
Button
, так и для
CheckBox теперь равно wrap_content
, так что каждому представлению выделяется место, достаточное только для его прорисовки (рис. 8.12).
(По области предварительного просмотра трудно понять, как работает систе- ма весов, потому что содержимое кнопки в макет не входит. На следующих рисунках показано, как будет выглядеть
LinearLayout
, если кнопка уже имеет содержимое.)
Рис. 8.12. Проход 1: распределение пространства на основании layout_width
На следующем проходе
LinearLayout распределяет дополнительное пространство на основании значений layout_weight
(рис. 8.13).
Рис. 8.13. Проход 2: распределение дополнительного пространства на основании layout_weight
В нашем макете
Button и
CheckBox имеют одинаковые значения layout_weight
, по- этому дополнительное пространство распределяется в соотношении 50/50. Если задать весовой коэффициент
Button равным 2, то ей будет выделено 2/3 дополни- тельного пространства, а
CheckBox достанется всего 1/3 (рис. 8.14).
Рис. 8.14. Неравномерное распределение дополнительного пространства с пропорцией layout_weight 2:1
В качестве весового коэффициента может использоваться любое вещественное число. Программисты используют разные системы обозначений весов. В файле

178
Глава 8. Макеты и виджеты fragment_crime.xml используется система «рецепт коктейля». Также часто применя- ются наборы весов, сумма которых составляет 1.0 или 100; в этом случае вес кнопки в приведенном примере составит 0.66 или 66 соответственно.
Что если вы хотите, чтобы виджет
LinearLayout выделял для каждого представле- ния ровно 50 % своей ширины? Просто пропустите первый проход, задав атрибуту layout_width каждого виджета значение
0dp вместо wrap_content
. В этом случае
LinearLayout принимает решения только на основании значений layout_weight
(рис. 8.15).
Рис. 8.15. При layout_width="0dp" учитываются только значения layout_weight
Графический конструктор макетов
Графический конструктор макетов удобен, и Android совершенствует его с каждым выпуском ADT. Однако порой он работает медленно и ненадежно и тогда про- ще использовать прямой ввод разметки XML. Вы можете переключаться между внесением изменений в графическом конструкторе и в XML (для надежности не забудьте сохранить файл перед переключением).
Не стесняйтесь использовать графический конструктор для создания макетов из этой книги. В дальнейшем, когда потребуется создать макет, мы будем приводить диаграмму наподобие рис. 8.6. Вы сами сможете решить, как создать ее — в виде разметки XML, в графическом конструкторе или сочетанием этих двух способов.
Идентификаторы виджетов и множественные макеты
Два макета, созданные для CriminalIntent, отличаются незначительно, но в неко- торых ситуациях возможны более серьезные расхождения. В таких случаях перед обращением к виджету в коде необходимо убедиться в том, что он действительно существует.
Если виджет присутствует в одном макете и отсутствует в другом, то для проверки его наличия в текущей ориентации перед вызовом методов следует использовать проверку null
:
Button landscapeOnlyButton = (Button)v.findViewById(R.id.landscapeOnlyButton);
if (landscapeOnlyButton != null) {
// Операции
}
Наконец, помните, что для того чтобы ваш код мог найти виджет, последний дол- жен иметь одинаковые значения атрибута android:id во всех макетах, в которых он присутствует.

Упражнение. Форматирование даты
179
Упражнение. Форматирование даты
Объект
Date больше напоминает временную метку (timestamp), чем традиционную дату. При вызове toString()
для
Date вы получаете именно временную метку, ко- торая отображается на кнопке. Временные метки хорошо подходят для отчетов, но на кнопке было бы лучше выводить дату в формате, более привычном для людей
(например, «Oct 12, 2012»). Для этого можно воспользоваться экземпляром класса android.text.format.DateFormat
. Хорошей отправной точкой в работе станет опи- сание этого класса в документации Android.
Используйте методы класса
DateFormat для формирования строки в стандартном формате или же подготовьте собственную форматную строку. Чтобы задача стала более творческой, попробуйте создать форматную строку для вывода дня неде- ли («Tuesday, Oct 12, 2012»).

Вывод списков
и ListFragment
Уровень модели CriminalIntent в настоящее время состоит из единственного эк- земпляра
Crime
. В этой главе мы обновим приложение CriminalIntent, чтобы оно поддерживало списки. В списке для каждого преступления будет отображаться краткое описание и дата, а также признак его раскрытия.
Рис. 9.1. Список преступлений
9

Обновление уровня модели CriminalIntent
181
На рис. 9.2 показана общая структура приложения CriminalIntent для этой главы.
Представление
Модель
Контроллер
Рис. 9.2. Приложение CriminalIntent со списком
На уровне модели появляется новый объект
CrimeLab
, который представляет собой централизованное хранилище для объектов
Crime
Для отображения списка на уровне контроллера CriminalIntent появляется новая активность и новый фрагмент:
CrimeListActivity и
CrimeListFragment
CrimeListFragment субклассирует
ListFragment
— субкласс
Fragment
, который обладает встроенными средствами для поддержки списков. Эти контроллеры вза- имодействуют друг с другом и
CrimeLab для обращения к данным уровня модели.
(Где находятся классы
CrimeActivity и
CrimeFragment на рис. 9.2? Они являются частью представления детализации, поэтому на рисунке их нет. В главе 10 мы свя- жем части списка и детализации CriminalIntent.)
На рис. 9.2 также видны объекты представлений, связанные с
CrimeListActivity и
CrimeListFragment
. Представление активности состоит из объекта
FrameLayout
, содержащего фрагмент. Представление фрагмента состоит из
ListView
. Взаимо- действие между
ListFragment и
ListView более подробно рассматривается позднее в этой главе.
Обновление уровня модели CriminalIntent
Прежде всего необходимо преобразовать уровень модели CriminalIntent из одного объекта
Crime в массив объектов
Crime
ArrayList
— класс Java, реализующий упорядоченный список объектов заданного типа. В нем содержатся методы извлечения, добавления и удаления элементов.

182
Глава 9. Вывод списков и ListFragment
Синглеты и централизованное хранение данных
Для хранения массива-списка преступлений будет использоваться синглетный
(singleton) класс. Такие классы допускают создание только одного экземпляра.
Экземпляр синглетного класса существует до тех пор, пока приложение остается в па- мяти, так что при хранении списка в синглетном объекте данные остаются доступными, что бы ни происходило с активностями, фрагментами и их жизненными циклами.
Чтобы создать синглетный класс, следует создать класс с закрытым конструктором и методом get()
, который возвращает экземпляр. Если экземпляр уже существует, то get()
просто возвращает его. Если экземпляр еще не существует, то get()
вы- зывает конструктор для его создания.
Щелкните правой кнопкой мыши на пакете com.bignerdranch.android.criminalintent и вы- берите команду
New

Class
. Введите имя класса
CrimeLab и щелкните на кнопке
Finish
В файле
CrimeLab.java реализуйте
CrimeLab как синглетный класс с закрытым кон- структором и методом get(Context)
Листинг 9.1. Синглетный класс (CrimeLab.java)
public class CrimeLab {
private static CrimeLab sCrimeLab;
private Context mAppContext;
private CrimeLab(Context appContext) {
mAppContext = appContext;
}
public static CrimeLab get(Context c) {
if (sCrimeLab == null) {
sCrimeLab = new CrimeLab(c.getApplicationContext());
}
return sCrimeLab;
}
}
Обратите внимание на префикс s
у переменной sCrimeLab
. Мы используем это ус- ловное обозначение Android, чтобы показать, что переменная sCrimeLab является статической.
Конструктору
CrimeLab передается параметр
Context
. В Android такая ситуация встречается очень часто; наличие параметра
Context позволяет синглетному классу запускать активности, обращаться к ресурсам проекта, находить закрытое храни- лище вашего приложения и т. д.
Обратите внимание: в get(Context)
параметр
Context не передается конструктору.
В
Context может содержаться
Activity или другой объект
Context
— например,
Service
. Мы не можем быть уверены в том, что произвольный объект
Context бу- дет существовать все то время, когда он может понадобиться
CrimeLab
— то есть на протяжении всего жизненного цикла приложения.
Чтобы гарантировать, что синглетному классу для работы будет доступен объект
Context с долгим сроком жизни, мы вызываем getApplicationContext()
и подменяем

Синглеты и централизованное хранение данных
183
переданный объект
Context
контекстом приложения. Контекст приложения глоба- лен по отношению к вашему приложению. Если в вашем приложении задействован синглетный класс уровня приложения, всегда используйте контекст приложения.
Для начала предоставим
CrimeLab несколько объектов
Crime для хранения. В кон- структоре
CrimeLab создайте пустой массив
ArrayList объектов
Crime
. Также добавьте два метода: getCrimes()
возвращает список, а getCrime(UUID)
возвращает объект
Crime с заданным идентификатором (листинг 9.2).
Листинг 9.2. Создание списка ArrayList объектов Crime (CrimeLab.java)
public class CrimeLab {
private ArrayList mCrimes;
private static CrimeLab sCrimeLab;
private Context mAppContext;
private CrimeLab(Context appContext) {
mAppContext = appContext;
mCrimes = new ArrayList();
}
public static CrimeLab get(Context c) {
}
public ArrayList getCrimes() {
return mCrimes;
}
public Crime getCrime(UUID id) {
for (Crime c : mCrimes) {
if (c.getId().equals(id))
return c;
}
return null;
}
}
Со временем
ArrayList будет содержать объекты
Crime
, созданные пользовате- лем, которые будут сохраняться и загружаться повторно. А пока заполним массив
100 однообразными объектами
Crime
(листинг 9.3).
Листинг 9.3. Генерирование тестовых объектов (CrimeLab.java)
private CrimeLab(Context appContext) {
mAppContext = appContext;
mCrimes = new ArrayList();
for (int i = 0; i < 100; i++) {
Crime c = new Crime();
c.setTitle("Crime #" + i);
c.setSolved(i % 2 == 0); // Для каждого второго объекта
mCrimes.add(c);
}
}

184
1   ...   13   14   15   16   17   18   19   20   ...   55

перейти в каталог файлов

Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей

Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей