Главная страница
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 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
страница18 из 55
КаталогОбразовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
1   ...   14   15   16   17   18   19   20   21   ...   55
Глава 9. Вывод списков и ListFragment
Теперь у нас имеется полностью загруженный уровень модели и 100 преступлений для вывода на экран.
Создание ListFragment
Создайте новый класс с именем
CrimeListFragment
. Щелкните на кнопке
Browse
, чтобы выбрать суперкласс. Найдите и выберите строку
ListFragment

android.support.v4.app
, после чего щелкните на кнопке
Finish
, чтобы сгенерировать класс
CrimeListFragment
Класс
ListFragment появился в Honeycomb, но он дублируется в библиотеке под- держки. Таким образом, с совместимостью проблем не будет — при условии, что вы используете класс библиотеки поддержки android.support.v4.app.ListFragment
В файле
CrimeListFragment.java переопределите метод onCreate(Bundle)
, чтобы задать заголовок активности, которая станет хостом данного фрагмента.
Листинг 9.4. Добавление метода onCreate(Bundle) в новую активность
(CrimeListFragment.java)
public class CrimeListFragment extends ListFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crimes_title);
}
}
Обратите внимание на метод getActivity()
. Этот вспомогательный метод
Fragment возвращает активность-хоста и позволяет фрагменту более активно выполнять функции активности. В приведенном примере он используется для вызова
Activ- ity.setTitle(int)
, заменяющего содержимое панели действий (строки заголовка на старых устройствах) значением переданного строкового ресурса.
Мы не будем переопределять onCreateView(…)
или заполнять макет
CrimeList-
Fragment
. Реализация
ListFragment по умолчанию заполняет макет, определяю- щий полноэкранный виджет
ListView
; пока мы будем использовать этот макет.
В следующих главах мы переопределим
CrimeListFragment.onCreateView(…)
для расширения функциональности приложения.
Добавьте в файл strings.xml строковый ресурс для заголовка активности списка.
Листинг 9.5. Добавление строкового ресурса для заголовка новой активности (strings.xml)
Solved?
Crimes
Классу
CrimeListFragment необходим доступ к списку преступлений, хранящемуся в
CrimeLab
. Включите в метод
CrimeListFragment.onCreate(…)
синглетный экземпляр
CrimeLab и получите список преступлений.

Абстрактная активность для хостинга фрагмента
185
Листинг 9.6. Обращение к данным списка в CrimeListFragment (CrimeListFragment.java)
public class CrimeListFragment extends ListFragment {
private ArrayList mCrimes;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crimes_title);
mCrimes = CrimeLab.get(getActivity()).getCrimes();
}
}
Абстрактная активность для хостинга фрагмента
Вскоре мы создадим класс
CrimeListActivity
, предназначенный для выполнения функций хоста для
CrimeListFragment
. Начнем с создания представления для
CrimeListActivity
Обобщенный макет для хостинга фрагмента
Для
CrimeListActivity можно просто воспользоваться макетом, определенным в файле activity_crime.xml
(листинг 9.7). Этот макет определяет виджет
FrameLayout как контейнерное представление для фрагмента, который затем указывается в коде активности.
Листинг 9.7. Файл activity_crime.xml уже содержит универсальную разметку

android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Поскольку в файле activity_crime.xml не указан конкретный фрагмент, он может ис- пользоваться для любой активности, выполняющей функции хоста для одного фрагмента. Переименуем его в activity_fragment.xml
, чтобы отразить этот факт.
Закройте файл activity_crime.xml в редакторе (если он открыт). Затем на панели Package
Explorer щелкните правой кнопкой мыши на файле res/layout/activity_crime.xml
. (Будьте внимательны — щелкнуть нужно на activity_crime.xml
, а не на fragment_crime.xml
.)
Выберите в контекстном меню команду
Refactor

Rename...
Введите имя activity_frag- ment.xml
. При переименовании ресурса ссылки на него обновляются автоматически.
В старых версиях ADT переименование ресурса не сопровождалось обновлением ссылок. Если Eclipse выдает сообщение об ошибке в
CrimeActivity.java
, вам придется вручную обновить ссылку
CrimeActivity
, как показано в листинге 9.8.
Листинг 9.8. Обновление файла макета для CrimeActivity (CrimeActivity.java)
public class CrimeActivity extends FragmentActivity {
/** Вызывается при исходном создании активности. */
продолжение


186
Глава 9. Вывод списков и ListFragment
Листинг 9.8 (продолжение)
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crime);
setContentView(R.layout.activity_fragment);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = new CrimeFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
}
Абстрактный класс Activity
Для создания класса
CrimeListActivity можно повторно использовать код
Crime-
Activity
. Взгляните на код, написанный для
CrimeActivity
(листинг 9.8): он прост и практически универсален. Собственно, в нем есть всего одно не-универсальное место: создание экземпляра
CrimeFragment перед его добавлением в
FragmentManager
Листинг 9.9. Класс CrimeActivity почти универсален (CrimeActivity.java)
public class CrimeActivity extends FragmentActivity {
/** Вызывается при исходном создании активности. */
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = new CrimeFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
}
Почти в каждой активности, которая будет создаваться в этой книге, будет при- сутствовать такой же код. Чтобы нам не приходилось вводить его снова и снова, мы выделим его в абстрактный класс.
Создайте новый класс с именем
SingleFragmentActivity в пакете CriminalIntent.
Сделайте его субклассом
FragmentActivity и установите флажок abstract
, чтобы сделать
SingleFragmentActivity абстрактным классом (рис. 9.3).

Абстрактная активность для хостинга фрагмента
187
Рис. 9.3. Создание абстрактного класса SingleFragmentActivity
Щелкните на кнопке
Finish и включите следующий фрагмент в
SingleFragmentActiv- ity.java
. Не считая выделенных частей, он идентичен старому коду
CrimeActivity
Листинг 9.10. Добавление обобщенного суперкласса (SingleFragmentActivity.java)
public abstract class SingleFragmentActivity extends FragmentActivity {
protected abstract Fragment createFragment();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
}

188
Глава 9. Вывод списков и ListFragment
В этом коде представление активности заполняется по данным activity_fragment.xml
Затем мы ищем фрагмент в
FragmentManager этого контейнера, создавая и добавляя его, если он не существует.
Код в листинге 9.10 отличается от кода
CrimeActivity только абстрактным мето- дом createFragment()
, который используется для создания экземпляра фрагмента.
Субклассы
SingleFragmentActivity реализуют этот метод так, чтобы возвращал экземпляр фрагмента, хостом которого является активность.
Использование абстрактного класса
Попробуем использовать класс с
CrimeListActivity
. Создайте новый класс с именем
CrimeListActivity
. Назначьте
SingleFragmentActivity его суперклассом в мастере.
Щелкните на кнопке
Browse
, введите имя
SingleFragmentActivity
, и Eclipse пред- ложит его в списке вариантов. Выберите его и нажмите кнопку
Finish
Рис. 9.4. Выбор SingleFragmentActivity
Eclipse открывает файл
CrimeListActivity.java
, в котором уже присутствует заготовка для createFragment()
. Метод возвращает новый экземпляр
CrimeListFragment
Листинг 9.11. Реализация CrimeListActivity (CrimeListActivity.java)
public class CrimeListActivity extends SingleFragmentActivity {
@Override protected Fragment createFragment() {
return new CrimeListFragment();
}
}

Абстрактная активность для хостинга фрагмента
189
Было бы лучше, если бы класс
CrimeActivity работал аналогичным образом. Вер- нитесь к файлу
CrimeActivity.java
. Удалите существующий код из
CrimeActivity и преобразуйте его в субкласс
SingleFragmentActivity
, как показано в листинге 9.12.
Листинг 9.12. Переработка CrimeListActivity (CrimeListActivity.java)
public class CrimeActivity extends FragmentActivity SingleFragmentActivity {
/** Вызывается при исходном создании активности. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = new CrimeFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
@Override
protected Fragment createFragment() {
return new CrimeFragment();
}
}
Класс
SingleFragmentActivity избавляет от ввода лишнего текста и сэкономит немало времени в примерах книги. Кроме того, с ним код активности становится более компактным и аккуратным.
Объявление CrimeListActivity
Теперь, когда класс
CrimeListActivity создан, его следует объявить в манифесте.
Кроме того, список преступлений должен выводиться на первом экране, который виден пользователю после запуска CriminalIntent; следовательно, активность
CrimeListActivity должна быть активностью лаунчера.
Включите в манифест объявление
CrimeListActivity и переместите фильтр интен- тов из объявления
CrimeActivity в объявление
CrimeListActivity
, как показано в листинге 9.13.
Листинг 9.13. Объявление CrimeListActivity активностью лаунчера (AndroidManifest.xml)
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

продолжение


190
Глава 9. Вывод списков и ListFragment
Листинг 9.13 (продолжение)





android:label="@string/app_name">


/>




CrimeListActivity теперь является активностью лаунчера. Запустите CriminalIn- tent; на экране появляется виджет
FrameLayout из
CrimeListActivity
, содержащий пустой фрагмент
CrimeListFragment
Рис. 9.5. Пустой экран CrimeListActivity
Когда у
ListView нет данных для отображения,
ListFragment выводит круговой индикатор прогресса. Мы предоставили
CrimeListFragment доступ к массиву объ- ектов
Crime
, но еще не сделали ничего, чтобы вывести их данные в
ListView
. Это станет нашей следующей задачей.

ListFragment, ListView и ArrayAdapter
191
ListFragment, ListView и ArrayAdapter
Вместо кругового индикатора в виджете
ListView из
CrimeListFragment должен отображаться список. Каждый элемент этого списка содержит данные об одном экземпляре
Crime
ListView является субклассом
ViewGroup
, а каждый элемент списка отображается как дочерний объект
View виджета
ListView
. В зависимости от сложности отобра- жаемых данных дочерние объекты
View могут быть сложными или очень простыми.
Наша первая реализация передачи данных для отображения будет очень простой: в элементе списка будет отображаться только краткое описание объекта
Crime
, а объект
View представляет собой простой виджет
TextView
Виджеты
TextView
Рис. 9.6. ListView с дочерними виджетами TextView
На рис. 9.6 видны 11 виджетов
TextView и часть 12-го. Если бы этот список можно было прокрутить, в виджете
ListView отобразились бы дополнительные виджеты
TextView

Crime
#12
,
Crime
#13
и т. д.
Откуда берутся эти объекты
View
? Может, полный список создается в
ListView заранее? Это было бы неэффективно. Объект
View должен существовать только тогда, когда он непосредственно находится на экране. Списки бывают огромными, создание и хранение объектов представления для всего списка создаст проблемы с быстродействием и памятью.

192
Глава 9. Вывод списков и ListFragment
Разумнее создавать объекты представлений только тогда, когда в них возникнет не- обходимость.
ListView запрашивает объект представления тогда, когда потребуется вывести определенный элемент списка.
К кому
ListView обращается с этим запросом? К своему адаптеру (adapter) — объ- екту контроллера, который находится между
ListView и набором данных с инфор- мацией, которую должен вывести
ListView
Адаптер отвечает за:

создание необходимого объекта представления;

заполнение его данными из уровня модели;

возвращение объекта представления
ListView
Адаптер представляет собой экземпляр класса, реализующего интерфейс
Adapter
Мы будем использовать экземпляр
ArrayAdapter
— адаптера, который умеет работать с данными массива (или
ArrayList
) объектов типа
T
На рис. 9.7 представлена «родословная» класса
ArrayAdapter
. Каждое звено цепи обеспечивает дополнительный уровень специализации.
является про- изводным от является про- изводным от является про- изводным от
Рис. 9.7. Иерархия наследования ArrayAdapter
Когда виджету
ListView требуется объект представления для отображения, он вступает в диалог со своим адаптером. На рис. 9.8 приведен пример возможного диалога
ListView с адаптером массива.
Сначала
ListView запрашивает общее количество объектов в массиве, для чего он вызывает метод getCount()
адаптера (это необходимо для того, чтобы избежать ошибок выхода за границу массива).

Создание ArrayAdapter
193
Представление для э лемента 0
Представление для э лемента 1
Представление для э лемента 2
Рис. 9.8. Диалог ListView-Adapter
Затем
ListView вызывает метод getView(int,
View,
ViewGroup)
адаптера. В первом аргументе передается позиция элемента списка, который нужен
ListView
В своей реализации getView(…)
адаптер создает объект представления по указан- ному элементу массива и возвращает этот объект представления объекту
ListView
Последний включает объект представления в себя как дочернее представление, в результате чего новое представление оказывается на экране.
Механика getView(…)
будет подробно описана далее в этой главе, когда мы пере- определим этот метод для создания нестандартных элементов списка.
Создание ArrayAdapter
Начнем с создания реализации
ArrayAdapter
по умолчанию для
CrimeListFrag- ment с использованием следующего конструктора:
public ArrayAdapter(Context context, int textViewResourceId, T[] objects)
В конструкторе адаптера массива первым параметром является объект
Context
, необходимый для использования идентификатора ресурса из второго параметра.
Идентификатор ресурса определяет макет, который будет использоваться
Ar- rayAdapter для создания объекта представления. В третьем параметре передается набор данных.
В файле
CrimeListFragment.java создайте экземпляр
ArrayAdapter
и назначьте его адаптером для виджета
ListView из
CrimeListFragment
(листинг 9.14).

194
Глава 9. Вывод списков и ListFragment
Листинг 9.14. Создание ArrayAdapter (CrimeListFragment.java)
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crimes_title);
mCrimes = CrimeLab.get(getActivity()).getCrimes();
ArrayAdapter adapter =
new ArrayAdapter(getActivity(),
android.R.layout.simple_list_item_1,
mCrimes);
setListAdapter(adapter);
}
setListAdapter(ListAdapter)
— вспомогательный метод
ListFragment
, который может использоваться для назначения адаптера объекта
ListView
, находящегося под управлением
CrimeListFragment
Макет, заданный в конструкторе адаптера (
android.R.layout.simple_list_item_1
), представляет собой заранее определенный макет из ресурсов, предоставляемых
Android SDK. Корневым элементом этого макета является элемент
TextView
Листинг 9.15. Исходный код android.R.layout.simple_list_item_1

В этом конструкторе также можно задать другой макет — при условии, что его корневым элементом является
TextView
Благодаря поведению по умолчанию, реализованному
ListFragment
, вы теперь мо- жете запустить приложение. Экземпляр
ListView будет успешно создан, появится на экране и начнет взаимодействовать со своим адаптером.
Запустите CriminalIntent. Вместо кругового индикатора в списке будут отобра- жаться элементы. Впрочем, текст, выводимый в каждом представлении, не особенно полезен для пользователя.
Реализация
ArrayAdapter.getView(…)
по умолчанию базируется на toString()
Она заполняет макет, находит нужный объект
Crime
, а затем вызывает toString()
для объекта, чтобы заполнить
TextView
Crime пока не переопределяет toString()
, поэтому используется реализация класса java.lang.Object
, которая возвращает полное имя класса и адрес памяти объекта.
Чтобы адаптер создавал более содержательное представление для
Crime
, откройте файл
Crime.java и переопределите метод toString()
так, чтобы он возвращал краткое описание преступления.

Создание ArrayAdapter
195
Листинг 9.16. Переопределение Crime.toString() (Crime.java)
public Crime() {
mId = UUID.randomUUID();
mDate = new Date();
}
@Override
public String toString() {
return mTitle;
}
Снова запустите CriminalIntent. Прокрутите список и просмотрите его элементы.
Рис. 9.9. Элементы списка с именем класса и адресами памяти
Рис. 9.10. Простые элементы списка с краткими описаниями преступлений
В процессе прокрутки
ListView вызывает метод getView(…)
адаптера для получения представлений, которые требуется отобразить.
Щелчки на элементах списка
Чтобы отреагировать на прикосновение пользователя к элементу списка, следует переопределить другой вспомогательный метод
ListFragment
:
public void onListItemClick(ListView l, View v, int position, long id)

196
1   ...   14   15   16   17   18   19   20   21   ...   55

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

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

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