| page.title=Фрагменты |
| parent.title=Операции |
| parent.link=activities.html |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>Содержание документа</h2> |
| <ol> |
| <li><a href="#Design">Философия проектирования</a></li> |
| <li><a href="#Creating">Создание фрагмента</a> |
| <ol> |
| <li><a href="#UI">Добавление пользовательского интерфейса</a></li> |
| <li><a href="#Adding">Добавление фрагмента в операцию</a></li> |
| </ol> |
| </li> |
| <li><a href="#Managing">Управление фрагментами</a></li> |
| <li><a href="#Transactions">Выполнение транзакций с фрагментами</a></li> |
| <li><a href="#CommunicatingWithActivity">Взаимодействие с операцией</a> |
| <ol> |
| <li><a href="#EventCallbacks">Создание обратного вызова события для операции</a></li> |
| <li><a href="#ActionBar">Добавление элементов в строку действий</a></li> |
| </ol> |
| </li> |
| <li><a href="#Lifecycle">Управление жизненным циклом фрагмента</a> |
| <ol> |
| <li><a href="#CoordinatingWithActivity">Согласование с жизненным циклом операции</a></li> |
| </ol> |
| </li> |
| <li><a href="#Example">Пример:</a></li> |
| </ol> |
| |
| <h2>Ключевые классы</h2> |
| <ol> |
| <li>{@link android.app.Fragment}</li> |
| <li>{@link android.app.FragmentManager}</li> |
| <li>{@link android.app.FragmentTransaction}</li> |
| </ol> |
| |
| <h2>См. также:</h2> |
| <ol> |
| <li><a href="{@docRoot}training/basics/fragments/index.html">Создание динамического интерфейса пользователя с использованием фрагментов</a></li> |
| <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Поддержка планшетов |
| и смартфонов</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p>Фрагмент (класс {@link android.app.Fragment}) представляет поведение или часть пользовательского интерфейса в операции |
| (класс {@link android.app.Activity}). Разработчик может объединить несколько фрагментов в одну операцию для построения |
| многопанельного пользовательского интерфейса и повторного использования фрагмента в нескольких операциях. Фрагмент можно рассматривать как |
| модульную часть операции. Такая часть имеет свой жизненный цикл и самостоятельно обрабатывает события ввода. Кроме того, |
| ее можно добавить или удалить непосредственно во время выполнения операции. Это нечто вроде вложенной операции, которую |
| можно многократно использовать в различных операциях.</p> |
| |
| <p>Фрагмент всегда должен быть встроен в операцию, и на его жизненный цикл напрямую |
| влияет жизненный цикл операции. Например, когда операция приостановлена, в том же состоянии находятся и все |
| фрагменты внутри нее, а когда операция уничтожается, уничтожаются и все фрагменты. Однако пока |
| операция выполняется (это соответствует состоянию <em>возобновлена</em> <a href="{@docRoot}guide/components/activities.html#Lifecycle">жизненного цикла</a>), можно |
| манипулировать каждым фрагментом независимо, например добавлять или удалять их. Когда разработчик выполняет такие |
| транзакции с фрагментами, он может также добавить их в стек переходов назад, которым управляет |
| операция. Каждый элемент стека переходов назад в операции является записью |
| выполненной транзакции с фрагментом. Стек переходов назад позволяет пользователю обратить транзакцию с фрагментом (выполнить навигацию в обратном направлении), |
| нажимая кнопку <em>Назад</em>.</p> |
| |
| <p>Когда фрагмент добавлен как часть макета операции, он находится в объекте {@link |
| android.view.ViewGroup} внутри иерархии представлений операции и определяет собственный |
| макет представлений. |
| Разработчик может вставить фрагмент в макет операции двумя способами. Для этого следует объявить фрагмент в |
| файле макета операции как элемент {@code <fragment>} или добавить его в |
| существующий объект{@link android.view.ViewGroup} в коде приложения. Впрочем, фрагмент не обязан быть частью |
| макета операции. Можно использовать фрагмент без интерфейса в качестве невидимого рабочего потока |
| операции.</p> |
| |
| <p>В этом документе показано, как построить приложение, использующее фрагменты. В частности, обсуждается, |
| как фрагменты могут поддерживать свое состояние, когда они добавляются в стек переходов назад операции, использовать |
| события совместно с операцией и другими фрагментами внутри нее, выводить данные в |
| строку действий операции и т. д.</p> |
| |
| |
| <h2 id="Design">Философия проектирования</h2> |
| |
| <p>Фрагменты впервые появились в Android версии 3.0 (API уровня 11), главным образом, для обеспечения |
| большей динамичности и гибкости пользовательских интерфейсов на больших экранах, например, у планшетов. Поскольку экраны |
| планшетов гораздо больше, чем у смартфонов, они предоставляют больше возможностей для объединения и |
| перестановки компонентов пользовательского интерфейса. Фрагменты позволяют делать это, избавляя разработчика от необходимости управлять |
| сложными изменениями в иерархии представлений. Разбивая макет операции на фрагменты, разработчик получает возможность |
| модифицировать внешний вид операции в ходе выполнения и сохранять эти изменения в стеке переходов назад, |
| которым управляет операция.</p> |
| |
| <p>Например, новостное приложение может использовать один фрагмент для показа списка статей слева, |
| а другой—для отображения статьи справа. Оба фрагмента отображаются за |
| одну операцию рядом друг с другом, и каждый имеет собственный набор методов обратного вызова жизненного цикла и управляет |
| собственными событиями пользовательского ввода. Таким образом, вместо применения одной операции для выбора статьи, а другой |
| — для чтения статей, пользователь может выбрать статью и читать ее в рамках одной |
| операции, как на планшете, изображенном на рисунке 1.</p> |
| |
| <p>Следует разрабатывать каждый фрагмент как модульный и повторно используемый компонент операции. Поскольку |
| каждый фрагмент определяет собственный макет и собственное поведение со своими обратными вызовами жизненного цикла, разработчик может |
| включить один фрагмент в несколько операций. Поэтому он должен предусмотреть повторное использование фрагмента и не допускать, |
| чтобы один фрагмент непосредственно манипулировал другим. Это особенно важно, потому что модульность фрагментов |
| позволяет изменять их сочетания в соответствии с различными размерами экранов. Если |
| приложение должно работать и на планшетах, и на смартфонах, можно повторно использовать фрагменты в различных |
| конфигурациях макета, чтобы оптимизировать взаимодействие с пользователем в зависимости от доступного размера экрана. Например, |
| на смартфоне может возникнуть необходимость в разделении фрагментов для предоставления однопанельного пользовательского интерфейса, если |
| разработчику не удается поместить более одного фрагмента в одну операцию.</p> |
| |
| <img src="{@docRoot}images/fundamentals/fragments.png" alt="" /> |
| <p class="img-caption"><strong>Рисунок 1.</strong> Пример того, как два модуля пользовательского интерфейса, определенные |
| фрагментами, могут быть объединены внутри одной операции для работы на планшетах, но разделены на |
| смартфонах.</p> |
| |
| <p>Вернемся к примеру с новостным приложением. Оно может иметь |
| два фрагмента, встроенных в <em>Операцию А</em>, когда выполняется на устройстве планшетного формата. В то же время на |
| экране смартфона недостаточно места для обоих фрагментов, и поэтому <em>Операция А</em> включает в себя |
| только фрагмент со списком статей. Когда пользователь выбирает статью, запускается |
| <em>Операция В</em>, содержащая второй фрагмент для чтения статьи. Таким образом, приложение |
| поддерживает как планшеты, так и смартфоны благодаря повторному использованию фрагментов в различных сочетаниях, как показано на |
| рисунке 1.</p> |
| |
| <p>Подробные сведения относительно разработки приложения с различными сочетаниями фрагментов для |
| различных конфигураций экрана приводятся в руководстве <a href="{@docRoot}guide/practices/tablets-and-handsets.html">Поддержка планшетов и смартфонов</a></p> |
| |
| |
| |
| <h2 id="Creating">Создание фрагмента</h2> |
| |
| <div class="figure" style="width:327px"> |
| <img src="{@docRoot}images/fragment_lifecycle.png" alt="" /> |
| <p class="img-caption"><strong>Рисунок 2.</strong> Жизненный цикл фрагмента (во время |
| выполнения операции)</p> |
| </div> |
| |
| <p>Для создания фрагмента необходимо создать подкласс класса {@link android.app.Fragment} (или его существующего |
| подкласса). Класс {@link android.app.Fragment} имеет код, во многом схожий с |
| кодом {@link android.app.Activity}. Он содержит методы обратного вызова, аналогичные методам операции, такие |
| как {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, |
| {@link android.app.Fragment#onPause onPause()} и {@link android.app.Fragment#onStop onStop()}. На практике, |
| если требуется преобразовать существующее приложение Android так, чтобы в нем использовались фрагменты, достаточно просто переместить |
| код из методов обратного вызова операции в соответствующие методы обратного вызова |
| фрагмента.</p> |
| |
| <p>Как правило, необходимо реализовать следующие методы жизненного цикла:</p> |
| |
| <dl> |
| <dt>{@link android.app.Fragment#onCreate onCreate()}</dt> |
| <dd>Система вызывает этот метод, когда создает фрагмент. В своей реализации разработчик должен |
| инициализировать ключевые компоненты фрагмента, которые требуется сохранить, когда фрагмент находится в состоянии |
| паузы или возобновлен после остановки.</dd> |
| <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> |
| <dd>Система вызывает этот метод при первом отображении пользовательского интерфейса фрагмента |
| на дисплее. Для прорисовки пользовательского интерфейса фрагмента следует возвратить из этого метода объект {@link android.view.View}, |
| который является корневым в макете фрагмента. Если фрагмент не имеет пользовательского интерфейса, можно |
| возвратить null.</dd> |
| <dt>{@link android.app.Activity#onPause onPause()}</dt> |
| <dd>Система вызывает этот метод как первое указание того, что пользователь покидает |
| фрагмент (это не всегда означает уничтожение фрагмента). Обычно именно в этот момент |
| необходимо фиксировать все изменения, которые должны быть сохранены за рамками текущего сеанса работы пользователя (поскольку |
| пользователь может не вернуться назад).</dd> |
| </dl> |
| |
| <p>В большинстве приложений для каждого фрагмента должны быть реализованы, как минимум, эти три метода. Однако существуют и |
| другие методы обратного вызова, которые следует использовать для управления различными этапами жизненного цикла |
| фрагмента. Все методы обратного вызова жизненного цикла подробно обсуждаются в разделе |
| <a href="#Lifecycle">Управление жизненным циклом фрагмента</a>.</p> |
| |
| |
| <p>Существует также ряд подклассов, которые, возможно, потребуется расширить вместо использования базового класса {@link |
| android.app.Fragment}:</p> |
| |
| <dl> |
| <dt>{@link android.app.DialogFragment}</dt> |
| <dd>Отображение перемещаемого диалогового окна. Использование этого класса для создания диалогового окна является хорошей альтернативой |
| вспомогательным методам диалогового окна в классе{@link android.app.Activity}. Дело в том, что он дает возможность |
| вставить диалоговое окно фрагмента в управляемый операцией стек переходов назад для фрагментов, |
| что позволяет пользователю вернуться к закрытому фрагменту.</dd> |
| |
| <dt>{@link android.app.ListFragment}</dt> |
| <dd>Отображение списка элементов, управляемых адаптером (например, {@link |
| android.widget.SimpleCursorAdapter}), аналогично классу {@link android.app.ListActivity}. Этот класс предоставляет |
| несколько методов для управления списком представлений, например, метод обратного вызова {@link |
| android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} для |
| обработки нажатий.</dd> |
| |
| <dt>{@link android.preference.PreferenceFragment}</dt> |
| <dd>Отображение иерархии объектов {@link android.preference.Preference} в виде списка, аналогично классу |
| {@link android.preference.PreferenceActivity}. Этот класс полезен, когда в приложении создается |
| операция «Настройки».</dd> |
| </dl> |
| |
| |
| <h3 id="UI">Добавление пользовательского интерфейса</h3> |
| |
| <p>Фрагмент обычно используется как часть пользовательского интерфейса операции, при этом он добавляет в операцию |
| свой макет.</p> |
| |
| <p>Чтобы создать макет для фрагмента, разработчик должен реализовать метод обратного вызова {@link |
| android.app.Fragment#onCreateView onCreateView()}, который система Android вызывает, |
| когда для фрагмента наступает время отобразить свой макет. Реализация этого метода должна возвращать объект |
| {@link android.view.View}, который является корневым в макете фрагмента. </p> |
| |
| <p class="note"><strong>Примечание.</strong> Если фрагмент является подклассом класса {@link |
| android.app.ListFragment}, реализация по умолчанию возвращает класс {@link android.widget.ListView} из метода |
| {@link android.app.Fragment#onCreateView onCreateView()}, так что реализовывать его нет необходиомости.</p> |
| |
| <p>Чтобы возвратить макет из метода {@link |
| android.app.Fragment#onCreateView onCreateView()}, можно выполнить его раздувание из <a href="{@docRoot}guide/topics/resources/layout-resource.html">ресурса макета</a>, определенного в XML-файле. Для |
| этой цели метод {@link android.app.Fragment#onCreateView onCreateView()} предоставляет объект |
| {@link android.view.LayoutInflater}.</p> |
| |
| <p>Например, код подкласса класса {@link android.app.Fragment}, загружающий макет из файла |
| {@code example_fragment.xml}, может выглядеть так:</p> |
| |
| <pre> |
| public static class ExampleFragment extends Fragment { |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| // Inflate the layout for this fragment |
| return inflater.inflate(R.layout.example_fragment, container, false); |
| } |
| } |
| </pre> |
| |
| <div class="sidebox-wrapper"> |
| <div class="sidebox"> |
| <h3>Создание макета</h3> |
| <p>В приведенном коде конструкция {@code R.layout.example_fragment} является ссылкой на ресурс макета |
| по имени {@code example_fragment.xml}, хранящийся в ресурсах приложения. Подробные сведения о |
| создании макета в XML см. в статье <a href="{@docRoot}guide/topics/ui/index.html">Пользовательский интерфейс</a>. |
| </p> |
| </div> |
| </div> |
| |
| <p>Параметр {@code container}, передаваемый методу {@link android.app.Fragment#onCreateView |
| onCreateView()}, является родительским классом {@link android.view.ViewGroup} (из макета операции), в который |
| будет вставлен макет |
| фрагмента. Параметр {@code savedInstanceState} является классом {@link android.os.Bundle}, который |
| предоставляет данные о предыдущем экземпляре фрагмента во время возобновления фрагмента |
| (восстановление состояния подробно обсуждается в разделе <a href="#Lifecycle">Управление |
| жизненным циклом фрагмента</a>).</p> |
| |
| <p>Метод {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} принимает |
| три аргумента:</p> |
| <ul> |
| <li>Идентификатор ресурса макета, раздувание которого следует выполнить.</li> |
| <li>Объект класса {@link android.view.ViewGroup}, который должен стать родительским для макета после раздувания. Передача параметра {@code |
| container} необходима для того, чтобы система смогла применить параметры макета к корневому представлению |
| раздутого макета, определяемому родительским представлением, в которое направляется макет.</li> |
| <li>Логическое значение, показывающее, следует ли прикрепить макет к объекту {@link |
| android.view.ViewGroup} (второй параметр) во время раздувания. (В данном случае это |
| false, потому что система уже вставляет раздутый макет в объект {@code |
| container}, ипередача значения true создала бы лишнюю группу представления в окончательном макете).</li> |
| </ul> |
| |
| <p>Мы увидели, как создавать фрагмент, предоставляющий макет. Теперь необходимо добавить |
| фрагмент в операцию.</p> |
| |
| |
| |
| <h3 id="Adding">Добавление фрагмента в операцию</h3> |
| |
| <p>Как правило, фрагмент добавляет часть пользовательского интерфейса в операцию, и этот интерфейс встраивается |
| в общую иерархию представлений операции. Разработчик может добавить фрагмент в макет операции двумя |
| способами:</p> |
| |
| <ul> |
| <li><b>объявив фрагмент в файле макета операции.</b> |
| <p>В этом случае можно |
| указать свойства макета для фрагмента, как будто он является представлением. Например, файл макета операции |
| с двумя фрагментами может выглядеть следующим образом:</p> |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| android:orientation="horizontal" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent"> |
| <fragment android:name="com.example.news.ArticleListFragment" |
| android:id="@+id/list" |
| android:layout_weight="1" |
| android:layout_width="0dp" |
| android:layout_height="match_parent" /> |
| <fragment android:name="com.example.news.ArticleReaderFragment" |
| android:id="@+id/viewer" |
| android:layout_weight="2" |
| android:layout_width="0dp" |
| android:layout_height="match_parent" /> |
| </LinearLayout> |
| </pre> |
| <p>Атрибут {@code android:name} в элементе {@code <fragment>} определяет класс {@link |
| android.app.Fragment}, экземпляр которого создается в макете.</p> |
| |
| <p>Когда система создает этот макет операции, она создает экземпляр каждого фрагмента, определенного в макете, |
| и для каждого вызывает метод {@link android.app.Fragment#onCreateView onCreateView()}, |
| чтобы получить макет каждого фрагмента. Система вставляет объект {@link android.view.View}, возвращенный |
| фрагментом, непосредственно вместо элемента {@code <fragment>}.</p> |
| |
| <div class="note"> |
| <p><strong>Примечание.</strong> Каждый фрагмент должен иметь уникальный идентификатор, который |
| система сможет использовать для восстановления фрагмента в случае перезапуска операции. (Что касается разработчика, он может использовать этот идентификатор для |
| захвата фрагмента с целью выполнения транзакций с ним, например, чтобы удалить его). Предоставить |
| идентификатор фрагменту можно тремя способами:</p> |
| <ul> |
| <li>указать атрибут {@code android:id} с уникальным идентификатором;</li> |
| <li>указать атрибут {@code android:tag} с уникальной строкой;</li> |
| <li>ничего не предпринимать, чтобы система использовала идентификатор контейнерного |
| представления.</li> |
| </ul> |
| </div> |
| </li> |
| |
| <li><b>или программным образом, добавив фрагмент в существующий объект {@link android.view.ViewGroup}.</b> |
| <p>В любой момент выполнения операции разработчик может добавить фрагменты в ее макет. Для |
| этого достаточно указать объект {@link |
| android.view.ViewGroup}, в котором следует разместить фрагмент.</p> |
| <p>Для выполнения транзакций с фрагментами внутри операции (таких как добавление, удаление или замена |
| фрагмента) необходимо использовать API-интерфейсы из {@link android.app.FragmentTransaction}. Экземпляр |
| класса {@link android.app.FragmentTransaction} можно получить от объекта {@link android.app.Activity} следующим образом:</p> |
| |
| <pre> |
| FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()} |
| FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; |
| </pre> |
| |
| <p>После этого можно добавить фрагмент методом {@link |
| android.app.FragmentTransaction#add(int,Fragment) add()}, указав добавляемый фрагмент и |
| представление, в которое он должен быть добавлен. Например:</p> |
| |
| <pre> |
| ExampleFragment fragment = new ExampleFragment(); |
| fragmentTransaction.add(R.id.fragment_container, fragment); |
| fragmentTransaction.commit(); |
| </pre> |
| |
| <p>Первый аргумент, передаваемый методу {@link android.app.FragmentTransaction#add(int,Fragment) add()}, |
| представляет собой контейнерный объект {@link android.view.ViewGroup} для фрагмента, указанный при помощи |
| идентификатора ресурса. Второй параметр — это фрагмент, который нужно добавить.</p> |
| <p>Выполнив изменения с помощью |
| {@link android.app.FragmentTransaction}, необходимо |
| вызвать метод {@link android.app.FragmentTransaction#commit}, чтобы они вступили в силу.</p> |
| </li> |
| </ul> |
| |
| |
| <h4 id="AddingWithoutUI">Добавление фрагмента, не имеющего пользовательского интерфейса</h4> |
| |
| <p>Пример, приведенный выше, демонстрирует, как добавлять в операцию фрагмент с предоставлением пользовательского интерфейса. Однако |
| можно использовать фрагмент и для реализации фонового поведения операции без какого-либо дополнительного |
| пользовательского интерфейса.</p> |
| |
| <p>Чтобы добавить фрагмент без пользовательского интерфейса, добавьте фрагмент из операции, используя метод {@link |
| android.app.FragmentTransaction#add(Fragment,String)} (передав ему уникальный строковый «тег» для |
| фрагмента вместо идентификатора представления). Фрагмент будет добавлен, но, поскольку он не связан |
| с представлением в макете операции, он не будет принимать вызов метода {@link |
| android.app.Fragment#onCreateView onCreateView()}. Поэтому в реализации этого метода нет необходимости.</p> |
| |
| <p>Передача строкового тега свойственна не только фрагментам без пользовательского интерфейса, поэтому можно |
| передавать строковые теги и фрагментам, имеющим пользовательский интерфейс. Однако, если у фрагмента нет |
| пользовательского интерфейса, то строковый тег является единственным способом его идентификации. Если впоследствии потребуется получить фрагмент от |
| операции, нужно будет вызвать метод {@link android.app.FragmentManager#findFragmentByTag |
| findFragmentByTag()}.</p> |
| |
| <p>Пример операции, использующей фрагмент в качестве фонового потока, без пользовательского интерфейса, приведен в образце кода {@code |
| FragmentRetainInstance.java}, входящем в число образцов в SDK (и доступном при помощи |
| Android SDK Manager). Путь к нему в системе — |
| <code><sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java</code>.</p> |
| |
| |
| |
| <h2 id="Managing">Управление фрагментами</h2> |
| |
| <p>Для управления фрагментами в операции нужен класс {@link android.app.FragmentManager}. Чтобы получить его, |
| следует вызвать метод {@link android.app.Activity#getFragmentManager()} из кода операции.</p> |
| |
| <p>Ниже указаны действия, которые позволяет выполнить{@link android.app.FragmentManager}:</p> |
| |
| <ul> |
| <li>получать фрагменты, имеющиеся в операции, с помощью метода {@link |
| android.app.FragmentManager#findFragmentById findFragmentById()} (для фрагментов, предоставляющих пользовательский интерфейс в |
| макете операции) или {@link android.app.FragmentManager#findFragmentByTag |
| findFragmentByTag()} (как для фрагментов, имеющих пользовательский интерфейс, так и для фрагментов без него);</li> |
| <li>снимать фрагменты со стека переходов назад методом {@link |
| android.app.FragmentManager#popBackStack()} (имитируя нажатие кнопки <em>Назад</em> пользователем);</li> |
| <li>регистрировать процесс-слушатель изменений в стеке переходов назад при помощи метода {@link |
| android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li> |
| </ul> |
| |
| <p>Дополнительные сведения об этих и других методах приводятся в документации по классу {@link |
| android.app.FragmentManager}.</p> |
| |
| <p>Как было показано в предыдущем разделе, можно использовать класс {@link android.app.FragmentManager} |
| для открытия {@link android.app.FragmentTransaction}, что позволяет выполнять транзакции с фрагментами, например, |
| добавление и удаление.</p> |
| |
| |
| <h2 id="Transactions">Выполнение транзакций с фрагментами</h2> |
| |
| <p>Большим достоинством использования фрагментов в операции является возможность добавлять, удалять, заменять их и |
| выполнять другие действия с ними в ответ на действия пользователя. Любой набор изменений, |
| вносимых в операцию, называется транзакцией. Ее можно выполнить при помощи API-интерфейсов в {@link |
| android.app.FragmentTransaction}. Каждую транзакцию можно сохранить в стеке переходов назад, |
| которым управляет операция. Это позволит пользователю перемещаться назад по изменениям во фрагментах (аналогично перемещению |
| назад по операциям).</p> |
| |
| <p>Экземпляр класса {@link android.app.FragmentTransaction} можно получить от {@link |
| android.app.FragmentManager}, например, так:</p> |
| |
| <pre> |
| FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}; |
| FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; |
| </pre> |
| |
| <p>Каждая транзакция является набором изменений, выполняемых одновременно. Разработчик может указать |
| все изменения, которые ему нужно выполнить в данной транзакции, вызывая методы {@link |
| android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()} |
| и {@link android.app.FragmentTransaction#replace replace()}. Затем, чтобы применить транзакцию |
| к операции, следует вызвать метод {@link android.app.FragmentTransaction#commit()}.</p> |
| </dl> |
| |
| <p>Впрочем, до вызова метода{@link |
| android.app.FragmentTransaction#commit()} у разработчика может возникнуть необходимость вызвать метод {@link |
| android.app.FragmentTransaction#addToBackStack addToBackStack()}, чтобы добавить транзакцию |
| в стек переходов назад по транзакциям фрагмента. Этим стеком переходов назад управляет операция, что позволяет |
| пользователю вернуться к предыдущему состоянию фрагмента, нажав кнопку <em>Назад</em>.</p> |
| |
| <p>Например, следующий код демонстрирует, как можно заменить один фрагмент другим, сохранив при этом предыдущее |
| состояние в стеке переходов назад:</p> |
| |
| <pre> |
| // Create new fragment and transaction |
| Fragment newFragment = new ExampleFragment(); |
| FragmentTransaction transaction = getFragmentManager().beginTransaction(); |
| |
| // Replace whatever is in the fragment_container view with this fragment, |
| // and add the transaction to the back stack |
| transaction.replace(R.id.fragment_container, newFragment); |
| transaction.addToBackStack(null); |
| |
| // Commit the transaction |
| transaction.commit(); |
| </pre> |
| |
| <p>В этом коде объект {@code newFragment} замещает фрагмент (если таковой имеется), находящийся в |
| контейнере макета, на который указывает идентификатор {@code R.id.fragment_container}. В результате вызова метода {@link |
| android.app.FragmentTransaction#addToBackStack addToBackStack()} транзакция замены |
| сохраняется в стеке переходов назад, чтобы пользователь мог обратить транзакцию и вернуть |
| предыдущий фрагмент, нажав кнопку <em>Назад</em>.</p> |
| |
| <p>Если в транзакцию добавить несколько изменений (например, еще раз вызвать {@link |
| android.app.FragmentTransaction#add add()} или {@link android.app.FragmentTransaction#remove |
| remove()}), а затем вызвать {@link |
| android.app.FragmentTransaction#addToBackStack addToBackStack()}, все изменения, примененные до вызова |
| метода {@link android.app.FragmentTransaction#commit commit()}, будут добавлены в стек |
| переходов назад как одна транзакция, и кнопка<em>Назад</em> обратит их все вместе.</p> |
| |
| <p>Порядок добавления изменений к объекту {@link android.app.FragmentTransaction} не играет роли |
| за следующими исключениями:</p> |
| <ul> |
| <li>метод {@link android.app.FragmentTransaction#commit()} должен быть вызван в последнюю очередь;</li> |
| <li>если в один контейнер добавляется несколько фрагментов, то порядок их |
| добавления определяет порядок, в котором они появляются в иерархии видов.</li> |
| </ul> |
| |
| <p>Если при выполнении транзакции, удаляющей фрагмент, не вызвать метод {@link android.app.FragmentTransaction#addToBackStack(String) |
| addToBackStack()}, при фиксации транзакции фрагмент |
| уничтожается, и пользователь теряет возможность вернуться к нему. В то же время, если |
| вызвать {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} при |
| удалении фрагмента, фрагмент перейдет в состояние <em>остановки</em> и будет возобновлен, если пользователь вернется |
| к нему.</p> |
| |
| <p class="note"><strong>Совет.</strong> К каждой транзакции с фрагментом можно применить анимацию |
| перехода, вызвав {@link android.app.FragmentTransaction#setTransition setTransition()} до |
| фиксации.</p> |
| |
| <p>Вызов метода {@link android.app.FragmentTransaction#commit()} не приводит к немедленному выполнению |
| транзакции. Метод запланирует ее выполнение в потоке пользовательского интерфейса операции (в «главном» потоке), как только |
| у потока появится возможность для этого. Впрочем, при необходимости можно вызвать {@link |
| android.app.FragmentManager#executePendingTransactions()} из потока пользовательского интерфейса, чтобы |
| транзакции, запланированные методом {@link android.app.FragmentTransaction#commit()} были выполнены немедленно. Как правило, |
| в этом нет необходимости, за исключением случаев, когда транзакция является зависимостью для заданий в других потоках.</p> |
| |
| <p class="caution"><strong>Внимание!</strong> Фиксировать транзакцию методом {@link |
| android.app.FragmentTransaction#commit commit()} можно только до того, как операция<a href="{@docRoot}guide/components/activities.html#SavingActivityState">сохранит свое |
| состояние</a> (после того, как пользователь покинет ее). Попытка зафиксировать транзакцию после этого момента |
| вызовет исключение. Дело в том, что состояние после фиксации может быть потеряно, если понадобится |
| восстановить операцию. В ситуациях, в которых потеря фиксации не критична, следует вызывать {@link |
| android.app.FragmentTransaction#commitAllowingStateLoss()}.</p> |
| |
| |
| |
| |
| <h2 id="CommunicatingWithActivity">Взаимодействие с операцией</h2> |
| |
| <p>Хотя {@link android.app.Fragment} реализован как объект, независимый от |
| класса {@link android.app.Activity}, и может быть использован внутри нескольких операций, конкретный экземпляр |
| фрагмента напрямую связан с содержащей его операцией.</p> |
| |
| <p>В частности, фрагмент может обратиться к экземпляру {@link android.app.Activity} с помощью метода {@link |
| android.app.Fragment#getActivity()} и без труда выполнить такие задачи, как поиск представления в макете |
| операции:</p> |
| |
| <pre> |
| View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list); |
| </pre> |
| |
| <p>Аналогичным образом операция может вызывать методы фрагмента, получив ссылку на объект |
| {@link android.app.Fragment} от {@link android.app.FragmentManager} с помощью метода {@link |
| android.app.FragmentManager#findFragmentById findFragmentById()} или {@link |
| android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. Например:</p> |
| |
| <pre> |
| ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment); |
| </pre> |
| |
| |
| <h3 id="EventCallbacks">Создание обратного вызова события для операции</h3> |
| |
| <p>В некоторых случаях необходимо, чтобы фрагмент использовал события совместно с операцией. Хороший способ реализации этого |
| состоит в том, чтобы определить интерфейс обратного вызова внутри фрагмента и потребовать от контейнерной операции |
| его реализации. Когда операция примет обратный вызов через этот интерфейс, она сможет обмениваться информацией с |
| другими фрагментами в макете по мере необходимости.</p> |
| |
| <p>Пусть, например, у новостного приложения имеются два фрагмента в одной операции: один для отображения списка |
| статей (фрагмент A), а другой—для отображения статьи (фрагмент B). Тогда фрагмент A должен сообщать |
| операции о том, что выбран пункт списка, чтобы она могла сообщить фрагменту B о необходимости отобразить статью. В |
| этом случае интерфейс {@code OnArticleSelectedListener} объявляется во фрагменте A:</p> |
| |
| <pre> |
| public static class FragmentA extends ListFragment { |
| ... |
| // Container Activity must implement this interface |
| public interface OnArticleSelectedListener { |
| public void onArticleSelected(Uri articleUri); |
| } |
| ... |
| } |
| </pre> |
| |
| <p>Тогда операция, содержащая этот фрагмент, реализует интерфейс {@code OnArticleSelectedListener} |
| и переопределит |
| метод {@code onArticleSelected()}, чтобы извещать фрагмент B о событии, исходящем от фрагмента A. Чтобы |
| контейнерная операция наверняка реализовала этот интерфейс, метод обратного вызова {@link |
| android.app.Fragment#onAttach onAttach()} во фрагменте A (который система вызывает при добавлении |
| фрагмента в операцию) создает экземпляр класса {@code OnArticleSelectedListener}, выполнив |
| приведение типа объекта {@link android.app.Activity}, который передается методу {@link android.app.Fragment#onAttach |
| onAttach()}:</p> |
| |
| <pre> |
| public static class FragmentA extends ListFragment { |
| OnArticleSelectedListener mListener; |
| ... |
| @Override |
| public void onAttach(Activity activity) { |
| super.onAttach(activity); |
| try { |
| mListener = (OnArticleSelectedListener) activity; |
| } catch (ClassCastException e) { |
| throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); |
| } |
| } |
| ... |
| } |
| </pre> |
| |
| <p>Если операция не реализовала интерфейс, фрагмент генерирует исключение |
| {@link java.lang.ClassCastException}. |
| В случае успеха элемент {@code mListener} будет содержать ссылку на реализацию интерфейса |
| {@code OnArticleSelectedListener} в операции, чтобы фрагмент A мог использовать |
| события совместно с операцией, вызывая методы, определенные интерфейсом {@code OnArticleSelectedListener}. Например, если фрагмент A является расширением |
| класса {@link android.app.ListFragment}, то всякий раз, |
| когда пользователь нажимает элемент списка, система вызывает {@link android.app.ListFragment#onListItemClick |
| onListItemClick()} во фрагменте. Этот метод, в свою очередь, вызывает метод {@code onArticleSelected()}, чтобы использовать |
| событие совместно с операцией:</p> |
| |
| <pre> |
| public static class FragmentA extends ListFragment { |
| OnArticleSelectedListener mListener; |
| ... |
| @Override |
| public void onListItemClick(ListView l, View v, int position, long id) { |
| // Append the clicked item's row ID with the content provider Uri |
| Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id); |
| // Send the event and Uri to the host activity |
| mListener.onArticleSelected(noteUri); |
| } |
| ... |
| } |
| </pre> |
| |
| <p>Параметр {@code id}, передаваемый методу {@link |
| android.app.ListFragment#onListItemClick onListItemClick()}, — это идентификатор строки с выбранным элементом списка, |
| который операция (или другой фрагмент) использует для получения статьи от объекта {@link |
| android.content.ContentProvider} приложения.</p> |
| |
| <p><!--To see a complete implementation of this kind of callback interface, see the <a |
| href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->Дополнительные сведения о |
| работе с поставщиком контента приводятся в документе <a href="{@docRoot}guide/topics/providers/content-providers.html">Поставщики контента</a>.</p> |
| |
| |
| |
| <h3 id="ActionBar">Добавление элементов в строку действий</h3> |
| |
| <p>Фрагменты могут добавлять пункты меню в <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Меню вариантов</a> операции (и, следовательно, в <a href="{@docRoot}guide/topics/ui/actionbar.html">Строку действий</a>), реализовав |
| {@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Однако, чтобы этот метод мог |
| принимать вызовы, необходимо вызывать {@link |
| android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} во время выполнения метода {@link |
| android.app.Fragment#onCreate(Bundle) onCreate()}, чтобы сообщить, что фрагмент |
| намеревается добавить пункты в Меню вариантов (в противном случае фрагмент не примет вызов метода |
| {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p> |
| |
| <p>Любые пункты, добавляемые фрагментом в Меню вариантов, присоединяются к |
| уже существующим. Кроме того, фрагмент принимает обратные вызовы метода {@link |
| android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}, когда пользователь выбирает пункт |
| меню.</p> |
| |
| <p>Разработчик может также зарегистрировать представление в макете своего фрагмента, чтобы предоставить контекстное меню. Для этого следует вызвать метод {@link |
| android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. Когда пользователь открывает |
| контекстное меню, фрагмент принимает вызов метода {@link |
| android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) |
| onCreateContextMenu()}. Когда пользователь выбирает пункт меню, фрагмент принимает вызов метода {@link |
| android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p> |
| |
| <p class="note"><strong>Примечание.</strong> Хотя фрагмент принимает обратный вызов по событию «выбран пункт меню» |
| для каждого добавленного им пункта, операция первой принимает соответствующий обратный вызов, когда пользователь |
| выбирает пункт меню. Если имеющаяся в операции реализация обратного вызова по событию «выбран пункт меню» не |
| обрабатывает выбранный пункт, событие передается методу обратного вызова во фрагменте. Это справедливо для |
| Меню вариантов и контекстных меню.</p> |
| |
| <p>Подробные сведения относительно меню см. в руководствах для разработчиков <a href="{@docRoot}guide/topics/ui/menus.html">Меню</a> и <a href="{@docRoot}guide/topics/ui/actionbar.html">Строка действий</a> </p> |
| |
| |
| |
| |
| <h2 id="Lifecycle">Управление жизненным циклом фрагмента</h2> |
| |
| <div class="figure" style="width:350px"> |
| <img src="{@docRoot}images/activity_fragment_lifecycle.png" alt="" /> |
| <p class="img-caption"><strong>Рисунок 3</strong>. Влияние жизненного цикла операции на жизненный цикл |
| фрагмента</p> |
| </div> |
| |
| <p>Управление жизненным циклом фрагмента во многом аналогично управлению жизненным циклом операции. Как и |
| операция, фрагмент может существовать в одном из трех состояний:</p> |
| |
| <dl> |
| <dt><i>Возобновлен</i></dt> |
| <dd>Фрагмент виден во время выполнения операции.</dd> |
| |
| <dt><i>Приостановлен</i></dt> |
| <dd>На переднем плане выполняется и находится в фокусе другая операция, но операция, содержащая данный |
| фрагмент, по-прежнему видна (операция переднего плана частично прозрачна или не |
| занимает весь экран).</dd> |
| |
| <dt><i>Остановлен</i></dt> |
| <dd>Фрагмент не виден. Либо контейнерная операция остановлена, либо |
| фрагмент удален из нее, но добавлен в стек переходов назад. Остановленный фрагмент |
| по-прежнему активен (вся информация о состоянии и элементах сохранена в системе). Однако он больше |
| не виден пользователю и будет уничтожен в случае уничтожения операции.</dd> |
| </dl> |
| |
| <p>Здесь снова просматривается аналогия с операцией: разработчик может сохранить состояние фрагмента с помощью {@link |
| android.os.Bundle} на случай, если процесс операции будет уничтожен, а разработчику понадобится восстановить |
| состояние фрагмента при повторном создании операции. Состояние можно сохранить во время выполнения метода обратного вызова {@link |
| android.app.Fragment#onSaveInstanceState onSaveInstanceState()} во фрагменте и восстановить его во время выполнения |
| {@link android.app.Fragment#onCreate onCreate()}, {@link |
| android.app.Fragment#onCreateView onCreateView()} или {@link |
| android.app.Fragment#onActivityCreated onActivityCreated()}. Дополнительные сведения о сохранении |
| состояния приводятся в документе <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Операции</a>. |
| </p> |
| |
| <p>Самое значительное различие в ходе жизненного цикла между операцией и фрагментом состоит в принципах |
| их сохранения в соответствующих стеках переходов назад. По умолчанию операция помещается в управляемый системой стек переходов назад для операций, |
| когда она останавливается (чтобы пользователь мог вернуться |
| к ней с помощью кнопки <em>Назад</em>, как описано в статье <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Задачи и стек переходов назад</a>). |
| В то же время, фрагмент помещается в стек переходов назад, управляемый операцией, только когда разработчик |
| явно запросит сохранение конкретного экземпляра, вызвав метод {@link |
| android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} во время транзакции, |
| удаляющей фрагмент.</p> |
| |
| <p>В остальном управление жизненным циклом фрагмента очень похоже на управление жизненным циклом |
| операции. Поэтому практические рекомендации по <a href="{@docRoot}guide/components/activities.html#Lifecycle">управлению жизненным циклом |
| операций</a> применимы и к фрагментам. При этом разработчику необходимо понимать, как жизненный цикл |
| операции влияет на жизненный цикл фрагмента.</p> |
| |
| <p class="caution"><strong>Внимание!</strong> Если возникнет необходимость в объекте {@link android.content.Context} |
| внутри объекта класса {@link android.app.Fragment}, можно вызвать метод{@link android.app.Fragment#getActivity()}. |
| Однако разработчик должен быть внимательным и вызывать метод {@link android.app.Fragment#getActivity()} только когда фрагмент |
| прикреплен к операции. Если фрагмент еще не прикреплен или был откреплен в конце |
| его жизненного цикла, метод {@link android.app.Fragment#getActivity()} возвратит null.</p> |
| |
| |
| <h3 id="CoordinatingWithActivity">Согласование с жизненным циклом операции</h3> |
| |
| <p>Жизненый цикл операции, содержащей фрагмент, непосредственным образом влияет на жизненый цикл |
| фрагмента, так что каждый обратный вызов жизненного цикла операции приводит к аналогичному обратного вызову для каждого |
| фрагмента. Например, когда операция принимает вызов {@link android.app.Activity#onPause}, каждый |
| ее фрагмент принимает {@link android.app.Fragment#onPause}.</p> |
| |
| <p>Однако у фрагментов есть несколько дополнительных методов обратного вызова жизненого цикла, которые обеспечивают уникальное взаимодействие с операцией |
| для выполнения таких действий, как создание и уничтожение пользовательского интерфейса фрагмента. Вот эти |
| методы:</p> |
| |
| <dl> |
| <dt>{@link android.app.Fragment#onAttach onAttach()}</dt> |
| <dd>Вызывается, когда фрагмент связывается с операцией (ему передается объект {@link |
| android.app.Activity}).</dd> |
| <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> |
| <dd>Вызывается для создания иерархии представлений, связанной с фрагментом.</dd> |
| <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt> |
| <dd>Вызывается, когда метод {@link android.app.Activity#onCreate |
| onCreate()}, принадлежащий операции, возвращает управление.</dd> |
| <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt> |
| <dd>Вызывается при удалении иерархии представлений, связанной с фрагментом.</dd> |
| <dt>{@link android.app.Fragment#onDetach onDetach()}</dt> |
| <dd>Вызывается при разрыве связи фрагмента с операцией.</dd> |
| </dl> |
| |
| <p>Зависимость жизненого цикла фрагмента от содержащей его операции иллюстрируется |
| рисунком 3. На этом рисунке можно видеть, что очередное состояние операции определяет, какие |
| методы обратного вызова может принимать фрагмент. Например, когда операция принимает свой метод обратного вызова {@link |
| android.app.Activity#onCreate onCreate()}, фрагмент внутри этой операции принимает всего лишь метод обратного вызова |
| {@link android.app.Fragment#onActivityCreated onActivityCreated()}.</p> |
| |
| <p>Когда операция переходит в состояние «возобновлена», можно свободно добавлять в нее фрагменты и удалять |
| их. Таким образом, жизненный цикл фрагмента может быть независимо изменен, только пока операция остается |
| в состоянии «возобновлена».</p> |
| |
| <p>Однако, когда операция выходит из этого состояния, продвижение фрагмента по его |
| жизненному циклу снова осуществляется операцией.</p> |
| |
| |
| |
| |
| <h2 id="Example">Пример:</h2> |
| |
| <p>Чтобы суммировать все сказанное в этом документе, рассмотрим пример операции, |
| использующей два фрагмента для создания макета с двумя панелями. Операция, код которой приведен ниже, включает в себя один фрагмент для |
| отображения списка пьес Шекспира, а другой — для отображения краткого содержания пьесы, выбранной |
| из списка. В примере показано, как следует организовывать различные конфигурации фрагментов |
| в зависимости от конфигурации экрана. </p> |
| |
| <p class="note"><strong>Примечание.</strong> Полный исходный код этой операции находится в разделе |
| <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code |
| FragmentLayout.java}</a>.</p> |
| |
| <p>Главная операция применяет макет обычным способом, в методе {@link |
| android.app.Activity#onCreate onCreate()}:</p> |
| |
| {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main} |
| |
| <p>Здесь применяется макет {@code fragment_layout.xml}:</p> |
| |
| {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} |
| |
| <p>Пользуясь этим макетом, система создает экземпляр класса {@code TitlesFragment} (список |
| пьес), как только операция загрузит макет. При этом объект {@link android.widget.FrameLayout} |
| (в котором будет находиться фрагмент с кратким содержанием) занимает место в правой части |
| экрана, но поначалу остается пустым. Как будет показано ниже, фрагмент не помещается в {@link android.widget.FrameLayout}, пока пользователь не выберет элемент |
| в списке.</p> |
| |
| <p>Однако не все экраны достаточно широки, чтобы отображать |
| краткое содержание рядом со списком пьес. Поэтому описанный выше макет используется только при альбомной ориентации |
| экрана и хранится в файле {@code res/layout-land/fragment_layout.xml}.</p> |
| |
| <p>Когда же устройство находится в книжной ориентации, система применяет макет, приведенный ниже, который |
| хранится в файле{@code res/layout/fragment_layout.xml}:</p> |
| |
| {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} |
| |
| <p>В этом макете присутствует только объект {@code TitlesFragment}. Это означает, что при |
| книжной ориентации устройства виден только список пьес. Когда пользователь нажимает на элемент |
| списка в этой конфигурации, приложение запускает новую операцию для отображения краткого содержания, |
| а не загружает второй фрагмент.</p> |
| |
| <p>Далее можно видеть, как это реализовано в классах фрагмента. Вначале идет код класса {@code |
| TitlesFragment}, отображающий список пьес Шекспира. Этот фрагмент является расширением класса {@link |
| android.app.ListFragment} и использует его функции для выполнения основной работы со списком.</p> |
| |
| <p>Изучая код, обратите внимание на то, что в качестве реакции на нажатие пользователем |
| элемента списка возможны две модели поведения. В зависимости от того, какой из двух макетов активен, либо в рамках одной операции создается и отображается новый фрагмент |
| с кратким содержанием (за счет добавления фрагмента в объект {@link |
| android.widget.FrameLayout}), либо запускается новая операция (отображающая фрагмент).</p> |
| |
| {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles} |
| |
| <p>Второй фрагмент, {@code DetailsFragment}, отображает краткое содержание пьесы, выбранной в |
| списке {@code TitlesFragment}:</p> |
| |
| {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details} |
| |
| <p>Вспомним код класса {@code TitlesFragment}: если пользователь нажимает на пункт списка, а |
| текущий макет <em>не</em> включает в себя представление {@code R.id.details} (которому принадлежит фрагмент |
| {@code DetailsFragment}), то приложение запускает операцию {@code DetailsActivity} |
| для отображения содержимого элемента.</p> |
| |
| <p>Далее идет код класса {@code DetailsActivity}, который всего лишь содержит объект {@code DetailsFragment} для отображения |
| краткого содержания выбранной пьесы на экране в книжной ориентации:</p> |
| |
| {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java |
| details_activity} |
| |
| <p>Обратите внимание, что в альбомной конфигурации эта операция самостоятельно завершается, чтобы главная |
| операция могла принять управление и отобразить фрагмент {@code DetailsFragment} рядом с фрагментом{@code TitlesFragment}. |
| Это может произойти, если пользователь запустит операцию {@code DetailsActivity} в книжной ориентации экрана, а |
| затем перевернет устройство в альбомную ориентацию (в результате чего текущая операция будет перезапущена).</p> |
| |
| |
| <p>Дополнительные образцы кода, использующего фрагменты (и файлы с полным исходным кодом этого примера), |
| доступны в приложении-примере API Demos в разделе <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment"> |
| ApiDemos</a> (которое можно загрузить из <a href="{@docRoot}resources/samples/get.html">компонента Samples SDK</a>).</p> |
| |
| |