Статьи

Дизайн пользовательского интерфейса Android: работа с фрагментами

Новый API Fragment для Android, представленный в Android 3.0, упрощает динамические пользовательские интерфейсы. В этом руководстве вы узнаете, как преобразовать двухэкранный рабочий процесс ListView в WebView в одноэкранный рабочий процесс, предназначенный для больших экранов, например, таких как планшеты.

Последующие изменения в методах и программном обеспечении

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

Эффект этого урока будет быстрее, чем у некоторых из наших уроков для начинающих; вам, возможно, придется просмотреть некоторые другие учебники по Android на этом сайте или даже в справочнике по Android SDK, если вы не знакомы с какими-либо базовыми концепциями и классами Android, обсуждаемыми в этом учебном пособии. Окончательный пример кода, прилагаемый к этому учебному пособию, доступен для загрузки с открытым исходным кодом с хостинга кодов Google .

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

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

На следующем рисунке показан существующий рабочий процесс нашего приложения для чтения статей Mobiletuts + (учебник ListView) до того, как дизайн фрагмента был рассмотрен и применен:

Фрагменты Android SDK - Рисунок 1

Этот рабочий процесс отлично работает на сравнительно небольшом экране телефона. Однако на большом экране, например на 10-дюймовом экране Motorola Xoom, на экране ListView слишком много свободного места. Экран WebView выглядит хорошо, хотя и немного скучно.

Именно здесь в игру вступают фрагменты: на больших экранах мы могли бы предоставить более эффективный пользовательский интерфейс, если бы могли отображать ListView на том же экране, что и WebView. Когда пользователь щелкает конкретный элемент ListView в левой «панели», WebView с правой стороны обновляется для отображения соответствующего содержимого. Этот тип рабочего процесса часто используется в программах чтения электронной почты или каналов. Следующий рисунок иллюстрирует именно такой редизайн:

Фрагменты Android SDK - Рисунок 2

Теперь, когда мы знаем, как будет разработан новый рабочий процесс экрана, мы также знаем, что два текущих действия необходимо будет преобразовать во фрагменты. Мы сделаем преобразование в несколько шагов. Первый шаг включает в себя оставление экранов визуально неизменными, но изменение каждого экрана для использования фрагмента. Один фрагмент будет содержать текущий ListView, а другой — WebView. Затем мы переключимся на одноэкранную реализацию, которая включает в себя изменение обмена сообщениями между активными действиями ListView и WebView.

Сначала измените Project Build Target вашего приложения на Android 3.0. Чтобы сделать это из Eclipse, щелкните правой кнопкой мыши проект и выберите «Свойства». Перейдите в раздел Android и установите флажок рядом с Android 3.0. Мы не используем API Google, поэтому достаточно версии Android с открытым исходным кодом. Затем нажмите кнопку ОК.

Теперь у вас будет доступ к новым API, включая API Fragments.

Примечание. В следующем руководстве мы поговорим об использовании нового уровня совместимости, чтобы технологии, такие как Fragment API, могли работать на более ранних версиях Android. Однако сейчас им потребуется устройство с Android 3.0, Honeycomb.

Создайте два новых Java-класса для представления двух фрагментов: экранов ListView и WebView. Назовите их TutListFragment и TutViewerFragment. TutListFragment расширит класс ListFragment, а TutViewerFragment просто расширит класс Fragment.

В классе TutListFragment нам необходимо переопределить два метода: onListItemClick () и onCreate (). Содержание этих методов должно выглядеть знакомым; они соответствуют тому, что мы ранее имели в классе TutListActivity. Это скоро изменится, но не только пока. Вот список класса TutListFragment, на данный момент:

Класс TutViewerFragment немного проще. Мы используем тот факт, что мы знаем (на данный момент), что фрагмент работает под тем же действием, которое он использовал, и извлекаем данные о намерениях непосредственно из класса Fragment. Добавьте метод переопределения для метода onCreateView (). Эти методы теперь должны выглядеть так:

Возможность прямого доступа к экземпляру действия полезна, но позже создаст проблему. Что если этот фрагмент находится на экране с фрагментом списка? В этом случае не будет никакого Запуска, чтобы получить URL от. Аналогично, в TutListFragment мы запускаем новую операцию непосредственно каждый раз, когда пользователь щелкает элемент в списке. Что, если TutViewFragment существовал в рамках одного и того же действия? Если это так, запуск нового действия не имеет смысла. Мы вернемся к решению этих проблем позже в этом руководстве.

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

1
2
3
4
5
6
7
8
<?xml version=»1.0″ encoding=»utf-8″?>
<fragment
    xmlns:android=»http://schemas.android.com/apk/res/android»
    android:name=»com.mamlambo.tutorial.tutlist.TutListFragment»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:id=»@+id/tutlist_fragment»>
</fragment>

Затем создайте похожий файл макета с именем tutview_fragment.xml:

1
2
3
4
5
6
7
8
<?xml version=»1.0″ encoding=»utf-8″?>
<fragment
    xmlns:android=»http://schemas.android.com/apk/res/android»
    android:name=»com.mamlambo.tutorial.tutlist.TutViewerFragment»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:id=»@+id/tutview_fragment»>
</fragment>

Классы TutListActivity и TutViewerActivity теперь должны быть обновлены. Класс TutListActivity имеет единственный метод onCreate (), который теперь должен быть обновлен для загрузки соответствующего ресурса макета фрагмента, созданного на предыдущем шаге, например:

Также следует отметить, что TutListActivity должна наследоваться от класса Activity, а не от ListActivity.

Класс TutViewerActivity требует аналогичного изменения. Его метод onCreate () теперь должен выглядеть так:

Попробуйте запустить приложение сейчас. Вы заметите, что он делает именно то, что делал раньше. Не очень интересно, правда? Однако весь пользовательский интерфейс теперь запускается с использованием фрагментов. Это позволит плавно вносить следующие изменения, которые необходимо внести, поскольку мы добавляем новый макет, чтобы объединить два фрагмента для больших дисплеев, которые будут отображаться пользователю на одном экране. Однако, как вы, возможно, заметили, связь между фрагментами обрабатывается идентично тому, как мы общаемся между действиями. Фактически, мы использовали знания о том, что активность, с которой был связан каждый фрагмент, осталась неизменной. Это не будет иметь место, когда у нас есть одно действие, которое содержит и управляет обоими фрагментами. Давайте сначала исправим это.

Как вы узнали на шаге 3, запуск действия непосредственно из объекта TutListFragment больше не имеет смысла. Пользовательский интерфейс WebView фактически может быть частью того же действия, что и список, — это наш план в любом случае для больших экранов. В этом случае мы просто хотим обновить URL-адрес WebView во втором фрагменте.

Чтобы сделать это изменение, нам нужно сделать несколько вещей. Во-первых, давайте сделаем фрагменты независимыми от деятельности, в которой они находятся. Для этого добавьте интерфейс слушателя к классу TutListFragment, например:

И затем запустите его, обновив метод onListItemClickListener () следующим образом:

Затем, пусть класс TutListActivity реализует интерфейс OnTutSelectedListener, например:

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

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

Сначала измените класс TutViewerFragment, чтобы он содержал новый метод с именем updateUrl ():

Затем удалите все функции из метода onCreateView (), кроме вызова inflate (). В классе TutViewerActivity добавьте функциональность обратно для получения Intent и затем вызовите метод updateUrl (), например, так:

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

Теперь давайте создадим макет с обоими фрагментами для использования в определенных ситуациях. В папке layout-land (которую вам может понадобиться создать) добавьте копию tutlist_fragment.xml. Это обеспечит различную компоновку для альбомной ориентации на любом ландшафтном экране. Портретный режим останется без изменений. Отредактируйте файл, чтобы он выглядел как следующий макет с обоими фрагментами:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout
    xmlns:android=»http://schemas.android.com/apk/res/android»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:orientation=»horizontal»>
    <fragment
        android:name=»com.mamlambo.tutorial.tutlist.TutListFragment»
        android:layout_width=»0dp»
        android:layout_height=»match_parent»
        android:id=»@+id/tutlist_fragment»
        android:layout_weight=»45″>
    </fragment>
    <fragment
        android:name=»com.mamlambo.tutorial.tutlist.TutViewerFragment»
        android:layout_width=»0dp»
        android:layout_height=»match_parent»
        android:id=»@+id/tutview_fragment»
        android:layout_weight=»55″>
    </fragment>
</LinearLayout>

Это разделит экран по горизонтали между обоими фрагментами.

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

Для этого обновите метод onTutSelected () класса TutListActivity следующим образом:

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

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

Фрагменты Android SDK - Урок 3

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

Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android» и « Самс научи себя разрабатывать приложения для Android за 24 часа» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте [email protected] , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .

Купить Android-разработку беспроводных приложений, 2-е издание Купить Sam's Teach Yourself для Android-разработки приложений в течение 24 часов Код Мамламбо в Код-Каньоне