blob: e8f6cd888ef84116d2a2e6fde1aa57002139bc3d [file] [log] [blame]
Scott Mainc18b5342010-08-17 11:48:09 -07001page.title=Fragments
Scott Mainb70afd32011-02-08 14:05:54 -08002parent.title=Activities
3parent.link=activities.html
Scott Mainc18b5342010-08-17 11:48:09 -07004@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8
9 <h2>Quickview</h2>
10 <ul>
Scott Main04d0e3d2011-01-14 15:20:32 -080011 <li>Fragments decompose application functionality and UI into reusable modules</li>
Scott Mainc18b5342010-08-17 11:48:09 -070012 <li>Add multiple fragments to a screen to avoid switching activities</li>
13 <li>Fragments have their own lifecycle, state, and back stack</li>
Scott Mainb6cf4b72011-10-27 12:49:15 -070014 <li>Fragments require API Level 11 or greater</li>
Scott Mainc18b5342010-08-17 11:48:09 -070015 </ul>
16
17 <h2>In this document</h2>
18 <ol>
Scott Main04d0e3d2011-01-14 15:20:32 -080019 <li><a href="#Design">Design Philosophy</a></li>
20 <li><a href="#Creating">Creating a Fragment</a>
21 <ol>
22 <li><a href="#UI">Adding a user interface</a></li>
23 <li><a href="#Adding">Adding a fragment to an activity</a></li>
24 </ol>
25 </li>
26 <li><a href="#Managing">Managing Fragments</a></li>
27 <li><a href="#Transactions">Performing Fragment Transactions</a></li>
28 <li><a href="#CommunicatingWithActivity">Communicating with the Activity</a>
29 <ol>
30 <li><a href="#EventCallbacks">Creating event callbacks to the activity</a></li>
31 <li><a href="#ActionBar">Adding items to the Action Bar</a></li>
32 </ol>
33 </li>
34 <li><a href="#Lifecycle">Handling the Fragment Lifecycle</a>
35 <ol>
Scott Main9c9b9ad2011-12-29 11:28:38 -080036 <li><a href="#CoordinatingWithActivity">Coordinating with the activity lifecycle</a></li>
Scott Main04d0e3d2011-01-14 15:20:32 -080037 </ol>
38 </li>
39 <li><a href="#Example">Example</a></li>
Scott Mainc18b5342010-08-17 11:48:09 -070040 </ol>
41
42 <h2>Key classes</h2>
43 <ol>
44 <li>{@link android.app.Fragment}</li>
45 <li>{@link android.app.FragmentManager}</li>
46 <li>{@link android.app.FragmentTransaction}</li>
47 </ol>
48
Scott Mainc18b5342010-08-17 11:48:09 -070049 <h2>Related samples</h2>
50 <ol>
51 <li><a
Scott Mainb6cf4b72011-10-27 12:49:15 -070052href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a></li>
53 <li><a
Scott Main04d0e3d2011-01-14 15:20:32 -080054href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">ApiDemos</a></li>
Scott Mainc18b5342010-08-17 11:48:09 -070055 </ol>
Scott Mainb6cf4b72011-10-27 12:49:15 -070056
57 <h2>See also</h2>
58 <ol>
59 <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets
60and Handsets</a></li>
61 </ol>
Scott Mainc18b5342010-08-17 11:48:09 -070062</div>
63</div>
64
Scott Main04d0e3d2011-01-14 15:20:32 -080065<p>A {@link android.app.Fragment} represents a behavior or a portion of user interface in an
66{@link android.app.Activity}. You can combine multiple fragments in a single activity to build a
67multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a
68modular section of an activity, which has its own lifecycle, receives its own input events, and
Scott Mainb6cf4b72011-10-27 12:49:15 -070069which you can add or remove while the activity is running (sort of like a "sub activity" that
70you can reuse in different activities).</p>
Scott Mainc18b5342010-08-17 11:48:09 -070071
Scott Main04d0e3d2011-01-14 15:20:32 -080072<p>A fragment must always be embedded in an activity and the fragment's lifecycle is directly
Scott Main60275012011-01-21 18:36:07 -080073affected by the host activity's lifecycle. For example, when the activity is paused, so are all
Scott Main04d0e3d2011-01-14 15:20:32 -080074fragments in it, and when the activity is destroyed, so are all fragments. However, while an
75activity is running (it is in the <em>resumed</em> <a
76href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">lifecycle state</a>), you can
77manipulate each fragment independently, such as add or remove them. When you perform such a
Scott Main60275012011-01-21 18:36:07 -080078fragment transaction, you can also add it to a back stack that's managed by the
Scott Main04d0e3d2011-01-14 15:20:32 -080079activity&mdash;each back stack entry in the activity is a record of the fragment transaction that
80occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards),
Scott Mainb6cf4b72011-10-27 12:49:15 -070081by pressing the BACK button.</p>
Scott Mainc18b5342010-08-17 11:48:09 -070082
Scott Main04d0e3d2011-01-14 15:20:32 -080083<p>When you add a fragment as a part of your activity layout, it lives in a {@link
Scott Mainb6cf4b72011-10-27 12:49:15 -070084android.view.ViewGroup} inside the activity's view hierarchy and the fragment defines its own view
85layout.
Scott Main04d0e3d2011-01-14 15:20:32 -080086You can insert a fragment into your activity layout by declaring the fragment in the activity's
87layout file, as a {@code &lt;fragment&gt;} element, or from your application code by adding it to an
88existing {@link android.view.ViewGroup}. However, a fragment is not required to be a part of the
Scott Mainb6cf4b72011-10-27 12:49:15 -070089activity layout; you may also use a fragment without its own UI as an invisible worker for the
90activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -070091
Scott Main04d0e3d2011-01-14 15:20:32 -080092<p>This document describes how to build your application to use fragments, including
93how fragments can maintain their state when added to the activity's back stack, share
94events with the activity and other fragments in the activity, contribute to the activity's action
95bar, and more.</p>
Scott Mainc18b5342010-08-17 11:48:09 -070096
Scott Main04d0e3d2011-01-14 15:20:32 -080097
98<h2 id="Design">Design Philosophy</h2>
99
Scott Mainb6cf4b72011-10-27 12:49:15 -0700100<p>Android introduced fragments in Android 3.0 (API level 11), primarily to support more
Scott Main04d0e3d2011-01-14 15:20:32 -0800101dynamic and flexible UI designs on large screens, such as tablets. Because a
Scott Mainb6cf4b72011-10-27 12:49:15 -0700102tablet's screen is much larger than that of a handset, there's more room to combine and
Scott Main04d0e3d2011-01-14 15:20:32 -0800103interchange UI components. Fragments allow such designs without the need for you to manage complex
104changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able
105to modify the activity's appearance at runtime and preserve those changes in a back stack
106that's managed by the activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700107
108<p>For example, a news application can use one fragment to show a list of articles on the
109left and another fragment to display an article on the right&mdash;both fragments appear in one
110activity, side by side, and each fragment has its own set of lifecycle callback methods and handle
Scott Main04d0e3d2011-01-14 15:20:32 -0800111their own user input events. Thus, instead of using one activity to select an article and another
Scott Mainc18b5342010-08-17 11:48:09 -0700112activity to read the article, the user can select an article and read it all within the same
Scott Mainb6cf4b72011-10-27 12:49:15 -0700113activity, as illustrated in the tablet layout in figure 1.</p>
114
115<p>You should design each fragment as a modular and reusable activity component. That is, because
116each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can
117include one fragment in multiple activities, so you should design for reuse and avoid directly
118manipulating one fragment from another fragment. This is especially important because a modular
119fragment allows you to change your fragment combinations for different screen sizes. When designing
120your application to support both tablets and handsets, you can reuse your fragments in different
121layout configurations to optimize the user experience based on the available screen space. For
122example, on a handset, it might be necessary to separate fragments to provide a single-pane UI when
123more than one cannot fit within the same activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700124
Scott Main04d0e3d2011-01-14 15:20:32 -0800125<img src="{@docRoot}images/fundamentals/fragments.png" alt="" />
Scott Mainb6cf4b72011-10-27 12:49:15 -0700126<p class="img-caption"><strong>Figure 1.</strong> An example of how two UI modules defined by
127fragments can be combined into one activity for a tablet design, but separated for a
128handset design.</p>
Scott Main04d0e3d2011-01-14 15:20:32 -0800129
130<p>For example&mdash;to continue with the news application example&mdash;the application can embed
Scott Mainb6cf4b72011-10-27 12:49:15 -0700131two fragments in <em>Activity A</em>, when running on a tablet-sized device. However, on a
132handset-sized screen, there's not be enough room for both fragments, so <em>Activity A</em> includes
133only the fragment for the list of articles, and when the user selects an article, it starts
134<em>Activity B</em>, which includes the second fragment to read the article. Thus, the application
135supports both tablets and handsets by reusing fragments in different combinations, as illustrated in
136figure 1.</p>
137
138<p>For more information about designing your application with different fragment combinations for
139different screen configurations, see the guide to <a
140href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets and Handsets</a>.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700141
142
143
144<h2 id="Creating">Creating a Fragment</h2>
145
Scott Main9c9b9ad2011-12-29 11:28:38 -0800146<div class="figure" style="width:327px">
Scott Main04d0e3d2011-01-14 15:20:32 -0800147<img src="{@docRoot}images/fragment_lifecycle.png" alt="" />
148<p class="img-caption"><strong>Figure 2.</strong> The lifecycle of a fragment (while its
149activity is running).</p>
150</div>
Scott Mainc18b5342010-08-17 11:48:09 -0700151
Scott Main04d0e3d2011-01-14 15:20:32 -0800152<p>To create a fragment, you must create a subclass of {@link android.app.Fragment} (or an existing
153subclass of it). The {@link android.app.Fragment} class has code that looks a lot like
154an {@link android.app.Activity}. It contains callback methods similar to an activity, such
155as {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()},
156{@link android.app.Fragment#onPause onPause()}, and {@link android.app.Fragment#onStop onStop()}. In
157fact, if you're converting an existing Android application to use fragments, you might simply move
158code from your activity's callback methods into the respective callback methods of your
159fragment.</p>
160
161<p>Usually, you should implement at least the following lifecycle methods:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700162
163<dl>
164 <dt>{@link android.app.Fragment#onCreate onCreate()}</dt>
165 <dd>The system calls this when creating the fragment. Within your implementation, you should
Scott Main04d0e3d2011-01-14 15:20:32 -0800166initialize essential components of the fragment that you want to retain when the fragment is
167paused or stopped, then resumed.</dd>
Scott Mainc18b5342010-08-17 11:48:09 -0700168 <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
169 <dd>The system calls this when it's time for the fragment to draw its user interface for the
170first time. To draw a UI for your fragment, you must return a {@link android.view.View} from this
171method that is the root of your fragment's layout. You can return null if the fragment does not
172provide a UI.</dd>
173 <dt>{@link android.app.Activity#onPause onPause()}</dt>
174 <dd>The system calls this method as the first indication that the user is leaving the
175fragment (though it does not always mean the fragment is being destroyed). This is usually where you
176should commit any changes that should be persisted beyond the current user session (because
177the user might not come back).</dd>
178</dl>
179
Scott Main04d0e3d2011-01-14 15:20:32 -0800180<p>Most applications should implement at least these three methods for every fragment, but there are
181several other callback methods you should also use to handle various stages of the
182fragment lifecycle. All the lifecycle callback methods are discussed more later, in the section
183about <a href="#Lifecycle">Handling the Fragment Lifecycle</a>.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700184
185
Scott Main04d0e3d2011-01-14 15:20:32 -0800186<p>There are also a few subclasses that you might want to extend, instead of the base {@link
187android.app.Fragment} class:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700188
189<dl>
190 <dt>{@link android.app.DialogFragment}</dt>
191 <dd>Displays a floating dialog. Using this class to create a dialog is a good alternative to using
Scott Main04d0e3d2011-01-14 15:20:32 -0800192the dialog helper methods in the {@link android.app.Activity} class, because you can
193incorporate a fragment dialog into the back stack of fragments managed by the activity,
194allowing the user to return to a dismissed fragment.</dd>
Scott Mainc18b5342010-08-17 11:48:09 -0700195
196 <dt>{@link android.app.ListFragment}</dt>
197 <dd>Displays a list of items that are managed by an adapter (such as a {@link
Scott Main04d0e3d2011-01-14 15:20:32 -0800198android.widget.SimpleCursorAdapter}), similar to {@link android.app.ListActivity}. It provides
199several methods for managing a list view, such as the {@link
Scott Mainc18b5342010-08-17 11:48:09 -0700200android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} callback to
Scott Main04d0e3d2011-01-14 15:20:32 -0800201handle click events.</dd>
Scott Mainc18b5342010-08-17 11:48:09 -0700202
203 <dt>{@link android.preference.PreferenceFragment}</dt>
204 <dd>Displays a hierarchy of {@link android.preference.Preference} objects as a list, similar to
Scott Main04d0e3d2011-01-14 15:20:32 -0800205{@link android.preference.PreferenceActivity}. This is useful when creating a "settings"
206activity for your application.</dd>
Scott Mainc18b5342010-08-17 11:48:09 -0700207</dl>
208
Scott Mainc18b5342010-08-17 11:48:09 -0700209
Scott Main04d0e3d2011-01-14 15:20:32 -0800210<h3 id="UI">Adding a user interface</h3>
Scott Mainc18b5342010-08-17 11:48:09 -0700211
Scott Main04d0e3d2011-01-14 15:20:32 -0800212<p>A fragment is usually used as part of an activity's user interface and contributes its own
213layout to the activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700214
Scott Main04d0e3d2011-01-14 15:20:32 -0800215<p>To provide a layout for a fragment, you must implement the {@link
216android.app.Fragment#onCreateView onCreateView()} callback method, which the Android system calls
217when it's time for the fragment to draw its layout. Your implementation of this method must return a
Scott Mainc18b5342010-08-17 11:48:09 -0700218{@link android.view.View} that is the root of your fragment's layout.</p>
219
Scott Main04d0e3d2011-01-14 15:20:32 -0800220<p class="note"><strong>Note:</strong> If your fragment is a subclass of {@link
221android.app.ListFragment}, the default implementation returns a {@link android.widget.ListView} from
222{@link android.app.Fragment#onCreateView onCreateView()}, so you don't need to implement it.</p>
223
224<p>To return a layout from {@link
225android.app.Fragment#onCreateView onCreateView()}, you can inflate it from a <a
226href="{@docRoot}guide/topics/resources/layout-resource.html">layout resource</a> defined in XML. To
227help you do so, {@link android.app.Fragment#onCreateView onCreateView()} provides a
228{@link android.view.LayoutInflater} object.</p>
229
230<p>For example, here's a subclass of {@link android.app.Fragment} that loads a layout from the
231{@code example_fragment.xml} file:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700232
233<pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800234public static class ExampleFragment extends Fragment {
Scott Mainc18b5342010-08-17 11:48:09 -0700235 &#64;Override
236 public View onCreateView(LayoutInflater inflater, ViewGroup container,
237 Bundle savedInstanceState) {
238 // Inflate the layout for this fragment
Scott Main04d0e3d2011-01-14 15:20:32 -0800239 return inflater.inflate(R.layout.example_fragment, container, false);
Scott Mainc18b5342010-08-17 11:48:09 -0700240 }
241}
242</pre>
243
Scott Main04d0e3d2011-01-14 15:20:32 -0800244<div class="sidebox-wrapper">
245<div class="sidebox">
246 <h3>Creating a layout</h3>
247 <p>In the sample above, {@code R.layout.example_fragment} is a reference to a layout resource
248named {@code example_fragment.xml} saved in the application resources. For information about how to
249create a layout in XML, see the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>
250documentation.</p>
251</div>
252</div>
253
254<p>The {@code container} parameter passed to {@link android.app.Fragment#onCreateView
255onCreateView()} is the parent {@link android.view.ViewGroup} (from the activity's layout) in which
256your fragment layout
257will be inserted. The {@code savedInstanceState} parameter is a {@link android.os.Bundle} that
258provides data about the previous instance of the fragment, if the fragment is being resumed
259(restoring state is discussed more in the section about <a href="#Lifecycle">Handling the
260Fragment Lifecycle</a>).</p>
261
Scott Mainc18b5342010-08-17 11:48:09 -0700262<p>The {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} method takes
263three arguments:</p>
264<ul>
Scott Main04d0e3d2011-01-14 15:20:32 -0800265 <li>The resource ID of the layout you want to inflate.</li>
266 <li>The {@link android.view.ViewGroup} to be the parent of the inflated layout. Passing the {@code
267container} is important in order for the system to apply layout parameters to the root view of the
268inflated layout, specified by the parent view in which it's going.</li>
269 <li>A boolean indicating whether the inflated layout should be attached to the {@link
270android.view.ViewGroup} (the second parameter) during inflation. (In this case, this
271is false because the system is already inserting the inflated layout into the {@code
272container}&mdash;passing true would create a redundant view group in the final layout.)</li>
Scott Mainc18b5342010-08-17 11:48:09 -0700273</ul>
274
Scott Main04d0e3d2011-01-14 15:20:32 -0800275<p>Now you've seen how to create a fragment that provides a layout. Next, you need to add
276the fragment to your activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700277
278
Scott Mainc18b5342010-08-17 11:48:09 -0700279
Scott Main04d0e3d2011-01-14 15:20:32 -0800280<h3 id="Adding">Adding a fragment to an activity</h3>
281
282<p>Usually, a fragment contributes a portion of UI to the host activity, which is embedded as a part
283of the activity's overall view hierarchy. There are two ways you can add a fragment to the activity
284layout:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700285
286<ul>
Scott Main04d0e3d2011-01-14 15:20:32 -0800287 <li><b>Declare the fragment inside the activity's layout file.</b>
Scott Mainc18b5342010-08-17 11:48:09 -0700288<p>In this case, you can
Scott Main04d0e3d2011-01-14 15:20:32 -0800289specify layout properties for the fragment as if it were a view. For example, here's the layout
290file for an activity with two fragments:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700291<pre>
292&lt;?xml version="1.0" encoding="utf-8"?&gt;
293&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
294 android:orientation="horizontal"
295 android:layout_width="match_parent"
296 android:layout_height="match_parent"&gt;
297 &lt;fragment android:name="com.example.news.ArticleListFragment"
298 android:id="@+id/list"
299 android:layout_weight="1"
300 android:layout_width="0dp"
301 android:layout_height="match_parent" /&gt;
302 &lt;fragment android:name="com.example.news.ArticleReaderFragment"
303 android:id="@+id/viewer"
304 android:layout_weight="2"
305 android:layout_width="0dp"
306 android:layout_height="match_parent" /&gt;
307&lt;/LinearLayout&gt;
308</pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800309 <p>The {@code android:name} attribute in the {@code &lt;fragment&gt;} specifies the {@link
310android.app.Fragment} class to instantiate in the layout.</p>
311
312<p>When the system creates this activity layout, it instantiates each fragment specified in the
313layout and calls the {@link android.app.Fragment#onCreateView onCreateView()} method for each one,
314to retrieve each fragment's layout. The system inserts the {@link android.view.View} returned by the
315fragment directly in place of the {@code &lt;fragment&gt;} element.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700316
317<div class="note">
318 <p><strong>Note:</strong> Each fragment requires a unique identifier that
319the system can use to restore the fragment if the activity is restarted (and which you can use to
Scott Main04d0e3d2011-01-14 15:20:32 -0800320capture the fragment to perform transactions, such as remove it). There are three ways to provide an
321ID for a fragment:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700322 <ul>
Scott Main04d0e3d2011-01-14 15:20:32 -0800323 <li>Supply the {@code android:id} attribute with a unique ID.</li>
324 <li>Supply the {@code android:tag} attribute with a unique string.</li>
325 <li>If you provide neither of the previous two, the system uses the ID of the container
326view.</li>
Scott Mainc18b5342010-08-17 11:48:09 -0700327 </ul>
328</div>
329 </li>
330
331 <li><b>Or, programmatically add the fragment to an existing {@link android.view.ViewGroup}.</b>
Scott Main04d0e3d2011-01-14 15:20:32 -0800332<p>At any time while your activity is running, you can add fragments to your activity layout. You
333simply need to specify a {@link
334android.view.ViewGroup} in which to place the fragment.</p>
335 <p>To make fragment transactions in your activity (such as add, remove, or replace a
Scott Mainc18b5342010-08-17 11:48:09 -0700336fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance
Scott Main04d0e3d2011-01-14 15:20:32 -0800337of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} like this:</p>
338
Scott Mainc18b5342010-08-17 11:48:09 -0700339<pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800340FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}
Dianne Hackborn17b9b812011-01-17 17:16:02 -0800341FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
Scott Mainc18b5342010-08-17 11:48:09 -0700342</pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800343
344<p>You can then add a fragment using the {@link
345android.app.FragmentTransaction#add(int,Fragment) add()} method, specifying the fragment to add and
346the view in which to insert it. For example:</p>
347
348<pre>
349ExampleFragment fragment = new ExampleFragment();
350fragmentTransaction.add(R.id.fragment_container, fragment);
351fragmentTransaction.commit();
352</pre>
353
354 <p>The first argument passed to {@link android.app.FragmentTransaction#add(int,Fragment) add()}
Scott Mainc18b5342010-08-17 11:48:09 -0700355is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by
Scott Main04d0e3d2011-01-14 15:20:32 -0800356resource ID, and the second parameter is the fragment to add.</p>
357 <p>Once you've made your changes with
Scott Mainc18b5342010-08-17 11:48:09 -0700358{@link android.app.FragmentTransaction}, you must
Scott Main04d0e3d2011-01-14 15:20:32 -0800359call {@link android.app.FragmentTransaction#commit} for the changes to take effect.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700360 </li>
361</ul>
362
363
Scott Main04d0e3d2011-01-14 15:20:32 -0800364<h4 id="AddingWithoutUI">Adding a fragment without a UI</h4>
Scott Mainc18b5342010-08-17 11:48:09 -0700365
Scott Main04d0e3d2011-01-14 15:20:32 -0800366<p>The examples above show how to add a fragment to your activity in order to provide a UI. However,
367you can also use a fragment to provide a background behavior for the activity without presenting
368additional UI.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700369
Scott Main04d0e3d2011-01-14 15:20:32 -0800370<p>To add a fragment without a UI, add the fragment from the activity using {@link
371android.app.FragmentTransaction#add(Fragment,String)} (supplying a unique string "tag" for the
372fragment, rather than a view ID). This adds the fragment, but, because it's not associated with a
373view in the activity layout, it does not receive a call to {@link
374android.app.Fragment#onCreateView onCreateView()}. So you don't need to implement that method.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700375
Scott Main04d0e3d2011-01-14 15:20:32 -0800376<p>Supplying a string tag for the fragment isn't strictly for non-UI fragments&mdash;you can also
377supply string tags to fragments that do have a UI&mdash;but if the fragment does not have a
378UI, then the string tag is the only way to identify it. If you want to get the fragment from the
379activity later, you need to use {@link android.app.FragmentManager#findFragmentByTag
380findFragmentByTag()}.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700381
Scott Main04d0e3d2011-01-14 15:20:32 -0800382<p>For an example activity that uses a fragment as a background worker, without a UI, see the <a
383href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.html">{@code
384FragmentRetainInstance.java}</a> sample.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700385
386
387
388<h2 id="Managing">Managing Fragments</h2>
389
Scott Main04d0e3d2011-01-14 15:20:32 -0800390<p>To manage the fragments in your activity, you need to use {@link android.app.FragmentManager}. To
391get it, call {@link android.app.Activity#getFragmentManager()} from your activity.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700392
Scott Main04d0e3d2011-01-14 15:20:32 -0800393<p>Some things that you can do with {@link android.app.FragmentManager} include:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700394
Scott Main04d0e3d2011-01-14 15:20:32 -0800395<ul>
396 <li>Get fragments that exist in the activity, with {@link
397android.app.FragmentManager#findFragmentById findFragmentById()} (for fragments that provide a UI in
398the activity layout) or {@link android.app.FragmentManager#findFragmentByTag
399findFragmentByTag()} (for fragments that do or don't provide a UI).</li>
400 <li>Pop fragments off the back stack, with {@link
401android.app.FragmentManager#popBackStack()} (simulating a BACK command by the user).</li>
402 <li>Register a listener for changes to the back stack, with {@link
403android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li>
404</ul>
Scott Mainc18b5342010-08-17 11:48:09 -0700405
Scott Main04d0e3d2011-01-14 15:20:32 -0800406<p>For more information about these methods and others, refer to the {@link
407android.app.FragmentManager} class documentation.</p>
408
409<p>As demonstrated in the previous section, you can also use {@link android.app.FragmentManager}
410to open a {@link android.app.FragmentTransaction}, which allows you to perform transactions, such as
411add and remove fragments.</p>
412
413
414<h2 id="Transactions">Performing Fragment Transactions</h2>
415
416<p>A great feature about using fragments in your activity is the ability to add, remove, replace,
417and perform other actions with them, in response to user interaction. Each set of changes that you
418commit to the activity is called a transaction and you can perform one using APIs in {@link
419android.app.FragmentTransaction}. You can also save each transaction to a back stack managed by the
420activity, allowing the user to navigate backward through the fragment changes (similar to navigating
421backward through activities).</p>
422
423<p>You can acquire an instance of {@link android.app.FragmentTransaction} from the {@link
424android.app.FragmentManager} like this:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700425
426<pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800427FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()};
Dianne Hackborn17b9b812011-01-17 17:16:02 -0800428FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
Scott Mainc18b5342010-08-17 11:48:09 -0700429</pre>
430
Scott Main04d0e3d2011-01-14 15:20:32 -0800431<p>Each transaction is a set of changes that you want to perform at the same time. You can set
432up all the changes you want to perform for a given transaction using methods such as {@link
433android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()},
434and {@link android.app.FragmentTransaction#replace replace()}. Then, to apply the transaction
435to the activity, you must call {@link android.app.FragmentTransaction#commit()}.</p>
436</dl>
437
438<p>Before you call {@link
439android.app.FragmentTransaction#commit()}, however, you might want to call {@link
440android.app.FragmentTransaction#addToBackStack addToBackStack()}, in order to add the transaction
441to a back stack of fragment transactions. This back stack is managed by the activity and allows
442the user to return to the previous fragment state, by pressing the BACK key.</p>
443
444<p>For example, here's how you can replace one fragment with another, and preserve the previous
445state in the back stack:</p>
446
447<pre>
448// Create new fragment and transaction
449Fragment newFragment = new ExampleFragment();
Dianne Hackborn17b9b812011-01-17 17:16:02 -0800450FragmentTransaction transaction = getFragmentManager().beginTransaction();
Scott Main04d0e3d2011-01-14 15:20:32 -0800451
452// Replace whatever is in the fragment_container view with this fragment,
453// and add the transaction to the back stack
454transaction.replace(R.id.fragment_container, newFragment);
455transaction.addToBackStack(null);
456
457// Commit the transaction
458transaction.commit();
459</pre>
460
461<p>In this example, {@code newFragment} replaces whatever fragment (if any) is currently in the
462layout container identified by the {@code R.id.fragment_container} ID. By calling {@link
463android.app.FragmentTransaction#addToBackStack addToBackStack()}, the replace transaction is
464saved to the back stack so the user can reverse the transaction and bring back the
Scott Mainc18b5342010-08-17 11:48:09 -0700465previous fragment by pressing the BACK key.</p>
466
Scott Main04d0e3d2011-01-14 15:20:32 -0800467<p>If you add multiple changes to the transaction (such as another {@link
468android.app.FragmentTransaction#add add()} or {@link android.app.FragmentTransaction#remove
469remove()}) and call {@link
470android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all changes applied
471before you call {@link android.app.FragmentTransaction#commit commit()} are added to the
472back stack as a single transaction and the BACK key will reverse them all together.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700473
Scott Main04d0e3d2011-01-14 15:20:32 -0800474<p>The order in which you add changes to a {@link android.app.FragmentTransaction} doesn't matter,
475except:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700476<ul>
477 <li>You must call {@link android.app.FragmentTransaction#commit()} last</li>
478 <li>If you're adding multiple fragments to the same container, then the order in which
Scott Main04d0e3d2011-01-14 15:20:32 -0800479you add them determines the order they appear in the view hierarchy</li>
Scott Mainc18b5342010-08-17 11:48:09 -0700480</ul>
Scott Main04d0e3d2011-01-14 15:20:32 -0800481
Scott Mainc18b5342010-08-17 11:48:09 -0700482<p>If you do not call {@link android.app.FragmentTransaction#addToBackStack(String)
483addToBackStack()} when you perform a transaction that removes a fragment, then that fragment is
Scott Main04d0e3d2011-01-14 15:20:32 -0800484destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you
485do call {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} when
486removing a fragment, then the fragment is <em>stopped</em> and will be resumed if the user navigates
487back.</p>
488
489<p class="note"><strong>Tip:</strong> For each fragment transaction, you can apply a transition
490animation, by calling {@link android.app.FragmentTransaction#setTransition setTransition()} before
491you commit.</p>
492
493<p>Calling {@link android.app.FragmentTransaction#commit()} does not perform the transaction
494immediately. Rather, it schedules it to run on the activity's UI thread (the "main" thread) as soon
495as the thread is able to do so. If necessary, however, you may call {@link
496android.app.FragmentManager#executePendingTransactions()} from your UI thread to immediately execute
497transactions submitted by {@link android.app.FragmentTransaction#commit()}. Doing so is
498usually not necessary unless the transaction is a dependency for jobs in other threads.</p>
499
500<p class="caution"><strong>Caution:</strong> You can commit a transaction using {@link
501android.app.FragmentTransaction#commit commit()} only prior to the activity <a
502href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">saving its
503state</a> (when the user leaves the activity). If you attempt to commit after that point, an
504exception will be thrown. This is because the state after the commit can be lost if the activity
505needs to be restored. For situations in which its okay that you lose the commit, use {@link
506android.app.FragmentTransaction#commitAllowingStateLoss()}.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700507
508
Scott Mainc18b5342010-08-17 11:48:09 -0700509
510
Scott Main04d0e3d2011-01-14 15:20:32 -0800511<h2 id="CommunicatingWithActivity">Communicating with the Activity</h2>
Scott Mainc18b5342010-08-17 11:48:09 -0700512
Scott Main04d0e3d2011-01-14 15:20:32 -0800513<p>Although a {@link android.app.Fragment} is implemented as an object that's independent from an
514{@link android.app.Activity} and can be used inside multiple activities, a given instance of
515a fragment is directly tied to the activity that contains it.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700516
Scott Main04d0e3d2011-01-14 15:20:32 -0800517<p>Specifically, the fragment can access the {@link android.app.Activity} instance with {@link
518android.app.Fragment#getActivity()} and easily perform tasks such as find a view in the
519activity layout:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700520
521<pre>
522View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
523</pre>
524
Scott Main04d0e3d2011-01-14 15:20:32 -0800525<p>Likewise, your activity can call methods in the fragment by acquiring a reference to the
526{@link android.app.Fragment} from {@link android.app.FragmentManager}, using {@link
527android.app.FragmentManager#findFragmentById findFragmentById()} or {@link
528android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. For example:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700529
530<pre>
Scott Main04d0e3d2011-01-14 15:20:32 -0800531ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
Scott Mainc18b5342010-08-17 11:48:09 -0700532</pre>
533
534
Scott Maina90eb8f2011-04-05 14:05:03 -0700535<h3 id="EventCallbacks">Creating event callbacks to the activity</h3>
Scott Mainc18b5342010-08-17 11:48:09 -0700536
537<p>In some cases, you might need a fragment to share events with the activity. A good way to do that
538is to define a callback interface inside the fragment and require that the host activity implement
Scott Main04d0e3d2011-01-14 15:20:32 -0800539it. When the activity receives a callback through the interface, it can share the information with
540other fragments in the layout as necessary.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700541
542<p>For example, if a news application has two fragments in an activity&mdash;one to show a list of
543articles (fragment A) and another to display an article (fragment B)&mdash;then fragment A must tell
544the activity when a list item is selected so that it can tell fragment B to display the article. In
Scott Main04d0e3d2011-01-14 15:20:32 -0800545this case, the {@code OnArticleSelectedListener} interface is declared inside fragment A:</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700546
547<pre>
548public static class FragmentA extends ListFragment {
549 ...
550 // Container Activity must implement this interface
Scott Main04d0e3d2011-01-14 15:20:32 -0800551 public interface OnArticleSelectedListener {
Scott Mainc18b5342010-08-17 11:48:09 -0700552 public void onArticleSelected(Uri articleUri);
553 }
554 ...
555}
556</pre>
557
Scott Main04d0e3d2011-01-14 15:20:32 -0800558<p>Then the activity that hosts the fragment implements the {@code OnArticleSelectedListener}
559interface and
Scott Mainc18b5342010-08-17 11:48:09 -0700560overrides {@code onArticleSelected()} to notify fragment B of the event from fragment A. To ensure
561that the host activity implements this interface, fragment A's {@link
Scott Main04d0e3d2011-01-14 15:20:32 -0800562android.app.Fragment#onAttach onAttach()} callback method (which the system calls when adding
563the fragment to the activity) instantiates an instance of {@code OnArticleSelectedListener} by
Scott Mainc18b5342010-08-17 11:48:09 -0700564casting the {@link android.app.Activity} that is passed into {@link android.app.Fragment#onAttach
565onAttach()}:</p>
566
567<pre>
568public static class FragmentA extends ListFragment {
Scott Main04d0e3d2011-01-14 15:20:32 -0800569 OnArticleSelectedListener mListener;
Scott Mainc18b5342010-08-17 11:48:09 -0700570 ...
571 &#64;Override
572 public void onAttach(Activity activity) {
573 super.onAttach(activity);
574 try {
Scott Main04d0e3d2011-01-14 15:20:32 -0800575 mListener = (OnArticleSelectedListener) activity;
Scott Mainc18b5342010-08-17 11:48:09 -0700576 } catch (ClassCastException e) {
Scott Main04d0e3d2011-01-14 15:20:32 -0800577 throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
Scott Mainc18b5342010-08-17 11:48:09 -0700578 }
579 }
580 ...
581}
582</pre>
583
Scott Main04d0e3d2011-01-14 15:20:32 -0800584<p>If the activity has not implemented the interface, then the fragment throws a
585{@link java.lang.ClassCastException}.
586On success, the {@code mListener} member holds a reference to activity's implementation of
587{@code OnArticleSelectedListener}, so that fragment A can share events with the activity by calling
588methods defined by the {@code OnArticleSelectedListener} interface. For example, if fragment A is an
Scott Mainc18b5342010-08-17 11:48:09 -0700589extension of {@link android.app.ListFragment}, each time
590the user clicks a list item, the system calls {@link android.app.ListFragment#onListItemClick
591onListItemClick()} in the fragment, which then calls {@code onArticleSelected()} to share
592the event with the activity:</p>
593
594<pre>
595public static class FragmentA extends ListFragment {
Scott Main04d0e3d2011-01-14 15:20:32 -0800596 OnArticleSelectedListener mListener;
Scott Mainc18b5342010-08-17 11:48:09 -0700597 ...
598 &#64;Override
599 public void onListItemClick(ListView l, View v, int position, long id) {
600 // Append the clicked item's row ID with the content provider Uri
601 Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id);
602 // Send the event and Uri to the host activity
Scott Main04d0e3d2011-01-14 15:20:32 -0800603 mListener.onArticleSelected(noteUri);
Scott Mainc18b5342010-08-17 11:48:09 -0700604 }
605 ...
606}
607</pre>
608
609<p>The {@code id} parameter passed to {@link
610android.app.ListFragment#onListItemClick onListItemClick()} is the row ID of the clicked item,
611which the activity (or other fragment) uses to fetch the article from the application's {@link
612android.content.ContentProvider}.</p>
613
614<p><!--To see a complete implementation of this kind of callback interface, see the <a
615href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->More information about
616using a content provider is available in the <a
617href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p>
618
619
620
Scott Main04d0e3d2011-01-14 15:20:32 -0800621<h3 id="ActionBar">Adding items to the Action Bar</h3>
Scott Mainc18b5342010-08-17 11:48:09 -0700622
Scott Main04d0e3d2011-01-14 15:20:32 -0800623<p>Your fragments can contribute menu items to the activity's <a
624href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> (and, consequently, the <a
625href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a>) by implementing
Scott Mainc18b5342010-08-17 11:48:09 -0700626{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. In order
627for this method to receive calls, however, you must call {@link
Scott Main04d0e3d2011-01-14 15:20:32 -0800628android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} during {@link
629android.app.Fragment#onCreate(Bundle) onCreate()}, to indicate that the fragment
630would like to add items to the Options Menu (otherwise, the fragment will not receive a call to
631{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700632
Scott Main04d0e3d2011-01-14 15:20:32 -0800633<p>Any items that you then add to the Options Menu from the fragment are appended to the existing
634menu items. The fragment also receives callbacks to {@link
635android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} when a menu item
636is selected.</p>
637
638<p>You can also register a view in your fragment layout to provide a context menu by calling {@link
Scott Mainc18b5342010-08-17 11:48:09 -0700639android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. When the user opens
640the context menu, the fragment receives a call to {@link
641android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo)
642onCreateContextMenu()}. When the user selects an item, the fragment receives a call to {@link
643android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
644
Scott Main04d0e3d2011-01-14 15:20:32 -0800645<p class="note"><strong>Note:</strong> Although your fragment receives an on-item-selected callback
646for each menu item it adds, the activity is first to receive the respective callback when the user
647selects a menu item. If the activity's implementation of the on-item-selected callback does not
648handle the selected item, then the event is passed to the fragment's callback. This is true for
649the Options Menu and context menus.</p>
650
Scott Mainb10b48f2011-09-13 16:40:52 -0700651<p>For more information about menus, see the <a
652href="{@docRoot}guide/topics/ui/menus.html">Menus</a> and <a
653href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guides.</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700654
655
656
657
Scott Main04d0e3d2011-01-14 15:20:32 -0800658<h2 id="Lifecycle">Handling the Fragment Lifecycle</h2>
659
Scott Main9c9b9ad2011-12-29 11:28:38 -0800660<div class="figure" style="width:350px">
Scott Main04d0e3d2011-01-14 15:20:32 -0800661<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt=""/>
662<p class="img-caption"><strong>Figure 3.</strong> The activity lifecycle's affect on the fragment
663lifecycle.</p>
664</div>
665
666<p>Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. Like
667an activity, a fragment can exist in three states:</p>
668
669<dl>
670 <dt><i>Resumed</i></dt>
671 <dd>The fragment is visible in the running activity.</dd>
672
673 <dt><i>Paused</i></dt>
674 <dd>Another activity is in the foreground and has focus, but the activity in which this
675fragment lives is still visible (the foreground activity is partially transparent or doesn't
676cover the entire screen).</dd>
677
678 <dt><i>Stopped</i></dt>
679 <dd>The fragment is not visible. Either the host activity has been stopped or the
680fragment has been removed from the activity but added to the back stack. A stopped fragment is
681still alive (all state and member information is retained by the system). However, it is no longer
682visible to the user and will be killed if the activity is killed.</dd>
683</dl>
684
685<p>Also like an activity, you can retain the state of a fragment using a {@link
686android.os.Bundle}, in case the activity's process is killed and you need to restore the
687fragment state when the activity is recreated. You can save the state during the fragment's {@link
688android.app.Fragment#onSaveInstanceState onSaveInstanceState()} callback and restore it during
689either {@link android.app.Fragment#onCreate onCreate()}, {@link
690android.app.Fragment#onCreateView onCreateView()}, or {@link
691android.app.Fragment#onActivityCreated onActivityCreated()}. For more information about saving
692state, see the <a
693href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">Activities</a>
694document.</p>
695
696<p>The most significant difference in lifecycle between an activity and a fragment is how one is
697stored in its respective back stack. An activity is placed into a back stack of activities
698that's managed by the system when it's stopped, by default (so that the user can navigate back
699to it with the BACK key, as discussed in <a
700href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>).
701However, a fragment is placed into a back stack managed by the host activity only when you
702explicitly request that the instance be saved by calling {@link
703android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} during a transaction that
704removes the fragment.</p>
705
706<p>Otherwise, managing the fragment lifecycle is very similar to managing the activity
707lifecycle. So, the same practices for <a
708href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">managing the activity
709lifecycle</a> also apply to fragments. What you also need to understand, though, is how the life
710of the activity affects the life of the fragment.</p>
711
712
713<h3 id="CoordinatingWithActivity">Coordinating with the activity lifecycle</h3>
714
715<p>The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the
716fragment, such that each lifecycle callback for the activity results in a similar callback for each
717fragment. For example, when the activity receives {@link android.app.Activity#onPause}, each
718fragment in the activity receives {@link android.app.Fragment#onPause}.</p>
719
720<p>Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the
721activity in order to perform actions such as build and destroy the fragment's UI. These additional
722callback methods are:</p>
723
724<dl>
725 <dt>{@link android.app.Fragment#onAttach onAttach()}</dt>
726 <dd>Called when the fragment has been associated with the activity (the {@link
727android.app.Activity} is passed in here).</dd>
728 <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
729 <dd>Called to create the view hierarchy associated with the fragment.</dd>
730 <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt>
731 <dd>Called when the activity's {@link android.app.Activity#onCreate
732onCreate()} method has returned.</dd>
733 <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt>
734 <dd>Called when the view hierarchy associated with the fragment is being removed.</dd>
735 <dt>{@link android.app.Fragment#onDetach onDetach()}</dt>
736 <dd>Called when the fragment is being disassociated from the activity.</dd>
737</dl>
738
739<p>The flow of a fragment's lifecycle, as it is affected by its host activity, is illustrated
740by figure 3. In this figure, you can see how each successive state of the activity determines which
741callback methods a fragment may receive. For example, when the activity has received its {@link
742android.app.Activity#onCreate onCreate()} callback, a fragment in the activity receives no more than
743the {@link android.app.Fragment#onActivityCreated onActivityCreated()} callback.</p>
744
745<p>Once the activity reaches the resumed state, you can freely add and remove fragments to the
746activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment
747change independently.</p>
748
749<p>However, when the activity leaves the resumed state, the fragment again is pushed through its
750lifecycle by the activity.</p>
751
752
753
754
755<h2 id="Example">Example</h2>
756
757<p>To bring everything discussed in this document together, here's an example of an activity
758using two fragments to create a two-pane layout. The activity below includes one fragment to
759show a list of Shakespeare play titles and another to show a summary of the play when selected
760from the list. It also demonstrates how to provide different configurations of the fragments,
761based on the screen configuration.</p>
762
763<p class="note"><strong>Note:</strong> The complete source code for this activity is available in
Scott Main13033ea2011-02-15 13:18:30 -0800764<a
765href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
Scott Main04d0e3d2011-01-14 15:20:32 -0800766FragmentLayout.java}</a>.</p>
767
768<p>The main activity applies a layout in the usual way, during {@link
769android.app.Activity#onCreate onCreate()}:</p>
770
771{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main}
772
773<p>The layout applied is {@code fragment_layout.xml}:</p>
774
775{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
776
777<p>Using this layout, the system instantiates the {@code TitlesFragment} (which lists the play
778titles) as soon as the activity loads the layout, while the {@link android.widget.FrameLayout}
779(where the fragment for showing the play summary will go) consumes space on the right side of the
780screen, but remains empty at first. As you'll see below, it's not until the user selects an item
781from the list that a fragment is placed into the {@link android.widget.FrameLayout}.</p>
782
783<p>However, not all screen configurations are wide enough to show both the list of
784plays and the summary, side by side. So, the layout above is used only for the landscape
785screen configuration, by saving it at {@code res/layout-land/fragment_layout.xml}.</p>
786
787<p>Thus, when the screen is in portrait orientation, the system applies the following layout, which
788is saved at {@code res/layout/fragment_layout.xml}:</p>
789
790{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
791
792<p>This layout includes only {@code TitlesFragment}. This means that, when the device is in
793portrait orientation, only the list of play titles is visible. So, when the user clicks a list
794item in this configuration, the application will start a new activity to show the summary,
795instead of loading a second fragment.</p>
796
797<p>Next, you can see how this is accomplished in the fragment classes. First is {@code
798TitlesFragment}, which shows the list of Shakespeare play titles. This fragment extends {@link
799android.app.ListFragment} and relies on it to handle most of the list view work.</p>
800
801<p>As you inspect this code, notice that there are two possible behaviors when the user clicks a
802list item: depending on which of the two layouts is active, it can either create and display a new
803fragment to show the details in the same activity (adding the fragment to the {@link
804android.widget.FrameLayout}), or start a new activity (where the fragment can be shown).</p>
805
806{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles}
807
808<p>The second fragment, {@code DetailsFragment} shows the play summary for the item selected from
809the list from {@code TitlesFragment}:</p>
810
811{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}
812
813<p>Recall from the {@code TitlesFragment} class, that, if the user clicks a list item and the
814current layout does <em>not</em> include the {@code R.id.details} view (which is where the
815{@code DetailsFragment} belongs), then the application starts the {@code DetailsActivity}
816activity to display the content of the item.</p>
817
818<p>Here is the {@code DetailsActivity}, which simply embeds the {@code DetailsFragment} to display
819the selected play summary when the screen is in portrait orientation:</p>
820
821{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
822details_activity}
823
824<p>Notice that this activity finishes itself if the configuration is landscape, so that the main
825activity can take over and display the {@code DetailsFragment} alongside the {@code TitlesFragment}.
826This can happen if the user begins the {@code DetailsActivity} while in portrait orientation, but
827then rotates to landscape (which restarts the current activity).</p>
828
829
830<p>For more samples using fragments (and complete source files for this example),
831see the sample code available in <a
832href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">
833ApiDemos</a> (available for download from the <a
834href="{@docRoot}resources/samples/get.html">Samples SDK component</a>).</p>
Scott Mainc18b5342010-08-17 11:48:09 -0700835
836