649 lines
32 KiB
Plaintext
649 lines
32 KiB
Plaintext
page.title=Fragments
|
|
@jd:body
|
|
|
|
<div id="qv-wrapper">
|
|
<div id="qv">
|
|
|
|
<h2>Quickview</h2>
|
|
<ul>
|
|
<li>Decompose application functionality and UI into reusable modules</li>
|
|
<li>Add multiple fragments to a screen to avoid switching activities</li>
|
|
<li>Fragments have their own lifecycle, state, and back stack</li>
|
|
<li>Fragments require API Level HONEYCOMB or greater</li>
|
|
</ul>
|
|
|
|
<h2>In this document</h2>
|
|
<ol>
|
|
<li><a href="#Creating">Creating fragments</a></li>
|
|
<li><a href="#Adding">Adding a fragment to an activity</a></li>
|
|
<li><a href="#Managing">Managing fragments</a></li>
|
|
<li><a href="#Lifecycle">Handling the lifecycle</a></li>
|
|
<li><a href="#Integrating">Integrating with the activity</a></li>
|
|
<li><a href="#Menus">Adding menus</a></li>
|
|
</ol>
|
|
|
|
<h2>Key classes</h2>
|
|
<ol>
|
|
<li>{@link android.app.Fragment}</li>
|
|
<li>{@link android.app.FragmentManager}</li>
|
|
<li>{@link android.app.FragmentTransaction}</li>
|
|
</ol>
|
|
|
|
<!--
|
|
<h2>Related samples</h2>
|
|
<ol>
|
|
<li><a
|
|
href="{@docRoot}resources/samples/NotePad/index.html">NotePad</a></li>
|
|
</ol>
|
|
-->
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<p>An {@link android.app.Activity} is always the window in which users interact with your
|
|
application, but a {@link android.app.Fragment} can be responsible for distinct operations and UI
|
|
that's embedded in an activity. So, when using fragments, your activity becomes more like a
|
|
container for fragments that define the activity's behavior and UI.</p>
|
|
|
|
<p>Fragments have their own
|
|
set of lifecylce callback methods and recieve their own user input events. A fragment must always be
|
|
embedded in an activity and the fragment's lifecycle is directly affected by the activity's
|
|
lifecycle. For example, when the activity is stopped, so are all fragments in it, and when
|
|
the activity is destroyed, so are all fragments. However, while an activity
|
|
is active (in the "resumed" lifecycle stage), you can manipulate the lifecycle of each fragment
|
|
independently. For example, you can add and remove fragments while the activity is active and you
|
|
can add each fragment to a back stack within the activity—each back stack entry in the
|
|
activity is actually a record of a "transaction" that occurred with the activity's fragments, so
|
|
that the user can reverse the transaction with the BACK key (this is discussed more later).</p>
|
|
|
|
<div class="figure" style="width:314px">
|
|
<img src="{@docRoot}images/fragment_lifecycle.png" alt="" />
|
|
<p class="img-caption"><strong>Figure 1.</strong> The lifecycle of a fragment (while its
|
|
activity is running).</p>
|
|
</div>
|
|
|
|
<p>Android introduced fragments in Android X.X (API Level HONEYCOMB), with the primary intention to
|
|
support more dynamic and flexible UI designs on large screen devices, such as tablets. Because a
|
|
tablet has a much larger screen than a mobile phone, there's more room to interchange UI
|
|
elements. Fragments allow that without the need for you to start a new activity or manage complex
|
|
changes to the view hierarchy. By dividing the layout of an activity into fragments, the code
|
|
that defines your activity becomes more modular and interchangable, allowing you to modify the
|
|
activity's appearance at runtime and for different types of screens.</p>
|
|
|
|
<p>For example, a news application can use one fragment to show a list of articles on the
|
|
left and another fragment to display an article on the right—both fragments appear in one
|
|
activity, side by side, and each fragment has its own set of lifecycle callback methods and handle
|
|
their own user input events. Thus, instead using one activity to select an article and another
|
|
activity to read the article, the user can select an article and read it all within the same
|
|
activity.</p>
|
|
|
|
<!-- ** TODO: Save this for later or move it down in the doc so the intro isn't overwhelming **
|
|
|
|
<p>A fragment can be a modular and reusable component in your application. That is, because
|
|
the fragment defines its own behavior using its own set of lifecycle callbacks, you can
|
|
include one fragment in multiple activities. This also enables you to create one version of your
|
|
application for multiple screen sizes. For instance, on an extra large screen (<em>xlarge</em>
|
|
screen configuration), you can embed two or more fragments in one activity, but on a normal-sized
|
|
screen (<em>normal</em> screen configuration), you can embed just one fragment in an activity and
|
|
then start other activities in order to display the other fragments.</p>
|
|
-->
|
|
|
|
<p>When you use a fragment as a part of your layout, it technically lives within a {@link
|
|
android.view.View} of the activity's layout and defines its own layout of views. You can insert a
|
|
fragment into your activity layout by declaring the fragment in the activity's XML layout file, as
|
|
a {@code <fragment>} element, or from your application code by adding it to an existing {@link
|
|
android.view.View}. However, a fragment is not required to be a part of the activity
|
|
layout—you might use a fragment as an invisible worker for the activity (more about that
|
|
later).</p>
|
|
|
|
<p>The rest of this document describes how to build your application to use fragments, including
|
|
how fragments can contribute to the activity options menu and action bar, create context menus,
|
|
maintain their state when added to the activity's back stack, and more.</p>
|
|
|
|
|
|
|
|
<h2 id="Creating">Creating a Fragment</h2>
|
|
|
|
<p>An implementation of the {@link android.app.Fragment} class contains code that looks a lot like
|
|
the code in an {@link android.app.Activity}. In fact, if you're
|
|
converting an existing Android application to use fragments, you'll move code
|
|
from your {@link android.app.Activity} implementation into your {@link android.app.Fragment} class
|
|
implementation, and into some of the same callback methods. A fragment contains callback methods
|
|
similar to an activity, such as {@link android.app.Fragment#onCreate onCreate()}, {@link
|
|
android.app.Fragment#onStart onStart()}, {@link android.app.Fragment#onPause onPause()}, and {@link
|
|
android.app.Fragment#onStop onStop()}.</p>
|
|
|
|
<p>If you're creating a fragment to be a modular piece of an activity UI, then your
|
|
implementation of {@link android.app.Fragment} should include most of the same lifecycle
|
|
callback methods traditionally implemented by the activity to initialize elements of the UI and
|
|
save and restore state information. Usually, you'll want to implement the following methods:</p>
|
|
|
|
<dl>
|
|
<dt>{@link android.app.Fragment#onCreate onCreate()}</dt>
|
|
<dd>The system calls this when creating the fragment. Within your implementation, you should
|
|
initialize the essential components of the fragment that should be retained when the fragment is
|
|
paused or stopped.</dd>
|
|
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
|
|
<dd>The system calls this when it's time for the fragment to draw its user interface for the
|
|
first time. To draw a UI for your fragment, you must return a {@link android.view.View} from this
|
|
method that is the root of your fragment's layout. You can return null if the fragment does not
|
|
provide a UI.</dd>
|
|
<dt>{@link android.app.Activity#onPause onPause()}</dt>
|
|
<dd>The system calls this method as the first indication that the user is leaving the
|
|
fragment (though it does not always mean the fragment is being destroyed). This is usually where you
|
|
should commit any changes that should be persisted beyond the current user session (because
|
|
the user might not come back).</dd>
|
|
</dl>
|
|
|
|
<p>Most applications should implement at least these three methods for each fragment, but there are
|
|
several other lifecycle callback methods that you should also use in order to provide the best
|
|
user experience when switching fragments and when the activity is paused or stopped. All of the
|
|
lifecycle callback methods are discussed more later, in
|
|
the section about <a href="#Lifecycle">Handling the Lifecycle</a>.</p>
|
|
|
|
|
|
<p>There are also a few different subclasses of {@link android.app.Fragment} that you might want
|
|
to use:</p>
|
|
|
|
<dl>
|
|
<dt>{@link android.app.DialogFragment}</dt>
|
|
<dd>Displays a floating dialog. Using this class to create a dialog is a good alternative to using
|
|
the dialog helper methods in the {@link android.app.Activity} class, because the dialog can be
|
|
incorporated into the fragment back stack managed by the activity.</dd>
|
|
|
|
<dt>{@link android.app.ListFragment}</dt>
|
|
<dd>Displays a list of items that are managed by an adapter (such as a {@link
|
|
android.widget.SimpleCursorAdapter}), similar to {@link android.app.ListActivity}. Provides methods
|
|
for managing a list, such as the {@link
|
|
android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} callback to
|
|
handle click events on list items.</dd>
|
|
|
|
<dt>{@link android.preference.PreferenceFragment}</dt>
|
|
<dd>Displays a hierarchy of {@link android.preference.Preference} objects as a list, similar to
|
|
{@link android.preference.PreferenceActivity}. </dd>
|
|
</dl>
|
|
|
|
<p>However, subclassing the standard {@link android.app.Fragment} class is most common, if
|
|
you're not creating a dialog, a list, or displaying preferences.</p>
|
|
|
|
|
|
<h3 id="UI">Providing a user interface</h3>
|
|
|
|
<p>To provide a UI layout for a fragment, you must implement
|
|
the {@link android.app.Fragment#onCreateView onCreateView()}
|
|
callback method in your {@link android.app.Fragment} (unless your fragment is a subclass of
|
|
{@link android.app.ListFragment}, which returns a {@link android.widget.ListView} from this method
|
|
by default). The Android system calls {@link android.app.Fragment#onCreateView onCreateView()} when
|
|
it's time for the fragment to draw its layout. Your implementation of this method must return a
|
|
{@link android.view.View} that is the root of your fragment's layout.</p>
|
|
|
|
<p>The easiest way to provide your layout is to inflate it from a <a
|
|
href="{@docRoot}guide/topics/resources/layout-resource.html">layout resource</a>. To help you
|
|
inflate a layout, the {@link android.app.Fragment#onCreateView onCreateView()} method passes a
|
|
{@link android.view.LayoutInflater} that you can use to get your layout. For example, here's a
|
|
simple subclass of {@link android.app.Fragment} that contains an implementation of {@link
|
|
android.app.Fragment#onCreateView onCreateView()} that loads the fragment's layout from a
|
|
resource:</p>
|
|
|
|
<pre>
|
|
public static class SimpleFragment extends Fragment {
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
// Inflate the layout for this fragment
|
|
return inflater.inflate(R.layout.simple_fragment, container, false);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>The {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} method takes
|
|
three arguments:</p>
|
|
<ul>
|
|
<li>The resource ID of the layout you want to inflate</li>
|
|
<li>The {@link android.view.ViewGroup} to be the parent of the
|
|
inflated layout (supplying this is important in order to apply layout parameters from the parent
|
|
view)</li>
|
|
<li>And a boolean indicating whether the inflated layout should be attached to the {@link
|
|
android.view.ViewGroup} (from the second parameter) during inflation (in this case, this
|
|
is false because the system is already going to insert the layout into the appropriate parent
|
|
view—doing otherwise would create a redundant view group in the final layout)</li>
|
|
</ul>
|
|
|
|
<p>The {@code container} parameter passed to {@link android.app.Fragment#onCreateView
|
|
onCreateView()} provides the parent {@link android.view.ViewGroup} in which your fragment layout
|
|
will be inserted, which you can use to generate layout parameters for your
|
|
fragment layout. The {@code savedInstanceState} parameter is a {@link android.os.Bundle} that
|
|
provides data about the previous instance of the fragment, if the fragment is being resumed
|
|
(restoring state is discussed more in the section about <a href="#Lifecycle">Handling the
|
|
Lifecycle</a>.</p>
|
|
|
|
|
|
<h3 id="Adding">Adding a Fragment to an Activity</h3>
|
|
|
|
<p>Each fragment is embedded into the layout of its container activity as a part of the overall view
|
|
hierarchy, whether or not it actually provides a UI. If a fragment is not embedded into the activity
|
|
layout, then it is never created (it does not receive any lifecycle callbacks). There are two ways
|
|
you can add a fragment to the activity layout:</p>
|
|
|
|
<ul>
|
|
<li><b>Declare the fragment inside the activity's layout XML file.</b>
|
|
<p>In this case, you can
|
|
specify layout properties for the fragment as if it were a view itself and the fragment's layout
|
|
fills that space. For example:</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>The {@code <fragment>} element uses the {@code android:name} attribute to specify the
|
|
{@link android.app.Fragment} class to instantiate and insert into the layout. When the activity
|
|
layout is created, the system instantiates each fragment in the layout and calls its {@link
|
|
android.app.Fragment#onCreateView onCreateView()} method in order to retrieve the fragment's
|
|
layout. The {@link android.view.View} object returned by {@link
|
|
android.app.Fragment#onCreateView onCreateView()} is then
|
|
placed directly in the activity layout in place of the {@code <fragment>} element.</p>
|
|
|
|
<div class="note">
|
|
<p><strong>Note:</strong> Each fragment requires a unique identifier that
|
|
the system can use to restore the fragment if the activity is restarted (and which you can use to
|
|
perform fragment transactions). There are three ways to identify a fragment:</p>
|
|
<ul>
|
|
<li>Supply the {@code android:id} attribute with a unique ID, in the {@code
|
|
<fragment>}</li>
|
|
<li>Supply the {@code android:tag} attribute with a unique string ID, in the {@code
|
|
<fragment>}</li>
|
|
<li>If neither of the previous two are provided, the system uses the ID of the container
|
|
view.</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
|
|
<li><b>Or, programmatically add the fragment to an existing {@link android.view.ViewGroup}.</b>
|
|
<p>At any time while your activity is running (in the "resumed" state), you can add (and remove)
|
|
fragments to your activity layout. You simply need to specify a {@link android.view.ViewGroup} in
|
|
which to place the fragment.</p>
|
|
<p>To make any fragment transactions in your activity (such as add, remove, or replace a
|
|
fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance
|
|
of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} using {@link
|
|
android.app.Activity#openFragmentTransaction()}. You can then add a fragment using the {@link
|
|
android.app.FragmentTransaction#add add()} method, specifying the fragment to add and the view in
|
|
which to insert it. For example:</p>
|
|
<pre>
|
|
MyFragment fragment = new MyFragment();
|
|
openFragmentTransaction().add(R.id.fragment_container, fragment).commit();
|
|
</pre>
|
|
<p>The first argument passed to {@link android.app.FragmentTransaction#add add()}
|
|
is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by
|
|
resource ID, and the second parameter is the fragment object.</p>
|
|
<p>Once you've made your changes using
|
|
{@link android.app.FragmentTransaction}, you must
|
|
call {@link android.app.FragmentTransaction#commit} in order for the changes to take effect.</p>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
<h3 id="Example1">Example: simple fragments</h3>
|
|
|
|
<p>In the last couple sections, you saw how to declare layout for a fragment and add it to an
|
|
activity. What follows is some code that brings it all together, like a "Hello World" for
|
|
fragments.</p>
|
|
|
|
<p>First, here's a layout file for a fragment:</p>
|
|
<pre>
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
android:orientation="vertical"
|
|
android:layout_width="match_parent"
|
|
android:layout_height="match_parent" >
|
|
<TextView
|
|
android:layout_width="match_parent"
|
|
android:layout_height="wrap_content"
|
|
android:text="@string/hello" />
|
|
<TextView
|
|
android:layout_width="match_parent"
|
|
android:layout_height="wrap_content"
|
|
android:text="@string/hello" />
|
|
</LinearLayout>
|
|
</pre>
|
|
|
|
<p>With that file saved at {@code res/layout/simple_fragment.xml}, the following {@link
|
|
android.app.Fragment} uses it for its layout:</p>
|
|
|
|
<pre>
|
|
public static class SimpleFragment extends Fragment {
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
// Inflate the layout for this fragment
|
|
return inflater.inflate(R.layout.simple_fragment, null);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>And the following layout for an activity applies the fragment twice, side by side:</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.SimpleFragment"
|
|
android:id="@+id/list"
|
|
android:layout_weight="1"
|
|
android:layout_width="0dp"
|
|
android:layout_height="match_parent" />
|
|
<fragment android:name="com.example.SimpleFragment"
|
|
android:id="@+id/viewer"
|
|
android:layout_weight="1"
|
|
android:layout_width="0dp"
|
|
android:layout_height="match_parent" />
|
|
</LinearLayout>
|
|
</pre>
|
|
|
|
<p>That's it. When an activity applies the previous layout as its content, the {@code
|
|
SimpleFragment} class is instantiated for each occurence in the layout, applying the fragment
|
|
layout when it receives the call to {@link android.app.Fragment#onCreateView onCreateView()}.</p>
|
|
|
|
<p>Although the fragment in this example implements only the {@link
|
|
android.app.Fragment#onCreateView onCreateView()} callback, there are several other lifecycle
|
|
callback methods that you should implement in your application. For example, {@link
|
|
android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onPause onPause()}, {@link
|
|
android.app.Fragment#onStop onStop()} and others that coincide with the fragment's lifecycle.</p>
|
|
|
|
|
|
|
|
<h2 id="Managing">Managing Fragments</h2>
|
|
|
|
<p>A useful feature of fragments is the ability to add, remove, replace, and perform other
|
|
operations on a fragment as the user interacts with the activity, alowing for more rich user
|
|
experiences without changing activities. In order to perform these operations, you must use {@link
|
|
android.app.FragmentTransaction} to perform fragment "transactions." You can acquire {@link
|
|
android.app.FragmentTransaction} from your activity with {@link
|
|
android.app.Activity#openFragmentTransaction}.</p>
|
|
|
|
<p>Common transactions you can perform with fragments include:</p>
|
|
|
|
<dl>
|
|
<dt>{@link android.app.FragmentTransaction#add add()}</dt>
|
|
<dd>Add a {@link android.app.Fragment} to the {@link android.app.Activity} layout.</dd>
|
|
<dt>{@link android.app.FragmentTransaction#remove remove()}</dt>
|
|
<dd>Remove a {@link android.app.Fragment} from the {@link android.app.Activity} layout.</dd>
|
|
<dt>{@link android.app.FragmentTransaction#replace replace()}</dt>
|
|
<dd>Replace an existing {@link android.app.Fragment} with another one.</dd>
|
|
</dl>
|
|
|
|
<p>For every transaction (or set of transactions) you perform, you must call {@link
|
|
android.app.FragmentTransaction#commit} in order for the transactions made with {@link
|
|
android.app.FragmentTransaction} to be applied. Before you do, however, you can call {@link
|
|
android.app.FragmentTransaction#addToBackStack} to add the current fragment state to the
|
|
activity's back stack, so that the user can return to the previous fragment state with the BACK key.
|
|
For example, here's how a new fragment can replace another one, but keep the previous fragment
|
|
in the back stack:</p>
|
|
|
|
<pre>
|
|
// Create new fragment
|
|
Fragment newFragment = new MyFragment();
|
|
FragmentTransaction ft = openFragmentTransaction();
|
|
// Replace and add to back stack
|
|
ft.replace(R.id.myfragment, newFragment);
|
|
ft.addToBackStack(null);
|
|
// Apply changes
|
|
ft.commit();
|
|
</pre>
|
|
|
|
<p>In this example, {@code newFragment} replaces whatever fragment is currently in the
|
|
layout container identified by the {@code R.id.myfragment} ID. By calling {@link
|
|
android.app.FragmentTransaction#addToBackStack addToBackStack()}, this transaction (the replace) is
|
|
saved to the activity's back stack so that the user can reverse this change and bring back the
|
|
previous fragment by pressing the BACK key.</p>
|
|
|
|
<p>If you perform multiple transactions and call {@link
|
|
android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all transactions performed
|
|
before {@link android.app.FragmentTransaction#commit} are added to the activity's back stack as a
|
|
single event and the BACK key will reverse them all together.</p>
|
|
|
|
|
|
|
|
<h2 id="Lifecycle">Handling the Lifecycle</h2>
|
|
|
|
<p>A fragment has a lifecycle that corresponds to the lifecycle of the activity in which it
|
|
resides. For example, a fragment has callback methods {@link
|
|
android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, {@link
|
|
android.app.Fragment#onPause onPause()}, {@link android.app.Fragment#onStop onStop()}, and more.</p>
|
|
|
|
<p>The lifecycle of the activity directly affects the lifecycle of the fragment, such that each
|
|
lifecycle callback for the activity results in a similar callback for each fragment (for
|
|
example, when the activity receives {@link android.app.Activity#onPause}, each fragment receives
|
|
{@link android.app.Fragment#onPause}). However, the
|
|
fragment's lifecycle can also change independently—but only while the activity is
|
|
resumed (while it is in the foreground)—because you can dynamically
|
|
add, remove, and replace fragments without any change to the lifecycle of the activity.</p>
|
|
|
|
<p>To accomodate backward navigation with the
|
|
BACK key, you can optionally maintain a back stack of fragment transactions, as described in the
|
|
previous section. So, if you
|
|
replace one fragment with another, the user can press the BACK key and view the previous
|
|
fragment. Additionally, each fragment can maintain its own state, such that
|
|
when the user navigates back to a previous fragment, the state of that fragment can be restored in
|
|
the same manner as the state of an activity is restored when it is stopped and restarted.</p>
|
|
|
|
<p>Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. A
|
|
fragment and an activity both have an "resumed," "paused," and "stopped" state, and they can both
|
|
retain their state using a {@link android.os.Bundle}. The only significant difference is that an
|
|
activity is placed into a the task's back stack by default (so that the user can navigate to
|
|
the previous activity with the BACK key), but a fragment is placed into the activity's back stack
|
|
only when you explicitly call {@link android.app.FragmentTransaction#addToBackStack(String)
|
|
addToBackStack()} before you {@link android.app.FragmentTransaction#commit()} a fragment
|
|
transaction.</p>
|
|
|
|
<p>The order in which you perform transactions with {@link android.app.FragmentTransaction} doesn't
|
|
matter, except:</p>
|
|
<ul>
|
|
<li>You must call {@link android.app.FragmentTransaction#commit()} last</li>
|
|
<li>If you're adding multiple fragments to the same container, then the order in which
|
|
you add them determines the order they appear</li>
|
|
</ul>
|
|
<p>If you do not call {@link android.app.FragmentTransaction#addToBackStack(String)
|
|
addToBackStack()} when you perform a transaction that removes a fragment, then that fragment is
|
|
destroyed when the transaction is committed.</p>
|
|
|
|
|
|
<h3 id="CoordinatingWithTheActivity">Coordinating with the activity lifecycle</h3>
|
|
|
|
<p>The lifecycle of an activity directly affects the lifecycle of a {@link android.app.Fragment}
|
|
embedded in that activity. The {@link android.app.Fragment} class has lifecycle callback
|
|
methods that match those in the {@link android.app.Activity} class.</p>
|
|
|
|
<p>Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the
|
|
activity in order to perform actions such as build and destroy the fragment's UI. These additional
|
|
callback methods are:</p>
|
|
|
|
<dl>
|
|
<dt>{@link android.app.Fragment#onAttach onAttach()}</dt>
|
|
<dd>Called when the fragment has been associated with the activity (the {@link
|
|
android.app.Activity} is passed in here).</dd>
|
|
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
|
|
<dd>Called to create the view hierarchy associated with the fragment.</dd>
|
|
<dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt>
|
|
<dd>Called when the activity's own {@link android.app.Activity#onCreate
|
|
onCreate()} has finished.</dd>
|
|
<dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt>
|
|
<dd>Called when the view hierarchy associated with the fragment is being removed.</dd>
|
|
<dt>{@link android.app.Fragment#onDetach onDetach()}</dt>
|
|
<dd>Called when the fragment is being disassociated from the activity.</dd>
|
|
</dl>
|
|
|
|
<p>The flow of a fragment's lifecycle, as it is affected by its container activity, is illustrated
|
|
by figure 3. In this figure, you can see how each successive state of the activity determines which
|
|
callback methods the fragment may receive. For example, when the activity has received
|
|
its {@link android.app.Activity#onCreate onCreate()} callback, the fragment receives no more
|
|
than the {@link android.app.Fragment#onActivityCreated onActivityCreated()} callback. However,
|
|
once the activity reaches the resumed state, you can freely add and remove fragments to the
|
|
activity, so the fragment lifecycle is no longer inhibitted by the state of the activity. Yet,
|
|
when the activity leaves the resumed state, the fragment again is pushed through its lifecycle by
|
|
the activity (unless you explicitly destroy the fragment sooner).</p>
|
|
|
|
|
|
<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt=""/>
|
|
<p class="img-caption"><strong>Figure 3.</strong> The activity lifecycle's affect on the lifecycle
|
|
of a fragment.</p>
|
|
|
|
|
|
<h3 id="Integrating">Integrating with the Activity</h3>
|
|
|
|
<p>Although a {@link android.app.Fragment} is implemented separate from an {@link
|
|
android.app.Activity} and can be used inside multiple activities, a fragment is directly tied to its
|
|
container activity and can access the Activity instance with {@link
|
|
android.app.Fragment#getActivity()}. So, a fragment can
|
|
easily perform tasks such as find a view in the activity:</p>
|
|
|
|
<pre>
|
|
View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
|
|
</pre>
|
|
|
|
<p>This makes it easy for your fragment to call public methods in the activity.</p>
|
|
|
|
<p>Likewise, your activity can call public methods in the fragment when you have a reference to the
|
|
{@link android.app.Fragment}. You can acquire a reference to the fragment with {@link
|
|
android.app.Activity#findFragmentById findFragmentById()} and cast it to your implementation of
|
|
{@link android.app.Fragment}. For example:</p>
|
|
|
|
<pre>
|
|
MyFragment fragment = (MyFragment) findFragmentById(R.id.myfragment);
|
|
fragment.refreshList();
|
|
</pre>
|
|
|
|
|
|
<h4 id="Callbacks">Creating event callbacks to the activity</h4>
|
|
|
|
<p>In some cases, you might need a fragment to share events with the activity. A good way to do that
|
|
is to define a callback interface inside the fragment and require that the host activity implement
|
|
it. When the activity receives a callback, it can share the information with other fragments in the layout as
|
|
necessary.</p>
|
|
|
|
<p>For example, if a news application has two fragments in an activity—one to show a list of
|
|
articles (fragment A) and another to display an article (fragment B)—then fragment A must tell
|
|
the activity when a list item is selected so that it can tell fragment B to display the article. In
|
|
this case, the following interface is defined inside fragment A:</p>
|
|
|
|
<pre>
|
|
public static class FragmentA extends ListFragment {
|
|
...
|
|
// Container Activity must implement this interface
|
|
public interface SelectedCallback {
|
|
public void onArticleSelected(Uri articleUri);
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>Then the activity that hosts the fragment implements the {@code SelectedCallback} interface and
|
|
overrides {@code onArticleSelected()} to notify fragment B of the event from fragment A. To ensure
|
|
that the host activity implements this interface, fragment A's {@link
|
|
android.app.Fragment#onAttach onAttach()} callback method (called when
|
|
the fragment is added to the activity) instantiates an instance of {@code SelectedCallback} by
|
|
casting the {@link android.app.Activity} that is passed into {@link android.app.Fragment#onAttach
|
|
onAttach()}:</p>
|
|
|
|
<pre>
|
|
public static class FragmentA extends ListFragment {
|
|
...
|
|
@Override
|
|
public void onAttach(Activity activity) {
|
|
super.onAttach(activity);
|
|
try {
|
|
mCallback = (SelectedCallback) activity;
|
|
} catch (ClassCastException e) {
|
|
activity.finish();
|
|
throw new ClassCastException(activity.toString() + " must implement SelectedCallback");
|
|
}
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>If the activity has not implemented the interface, then a {@link java.lang.ClassCastException} is
|
|
thrown and the activity is shut down. On success, the {@code mCallback} member holds a reference to
|
|
the {@link android.app.Activity}, so that fragment A can share events with the activity by calling
|
|
methods defined by the {@code SelectedCallback} interface. For example, if fragment A is an
|
|
extension of {@link android.app.ListFragment}, each time
|
|
the user clicks a list item, the system calls {@link android.app.ListFragment#onListItemClick
|
|
onListItemClick()} in the fragment, which then calls {@code onArticleSelected()} to share
|
|
the event with the activity:</p>
|
|
|
|
<pre>
|
|
public static class FragmentA extends ListFragment {
|
|
...
|
|
@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
|
|
mCallback.onArticleSelected(noteUri);
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>The {@code id} parameter passed to {@link
|
|
android.app.ListFragment#onListItemClick onListItemClick()} is the row ID of the clicked item,
|
|
which the activity (or other fragment) uses to fetch the article from the application's {@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>. -->More information about
|
|
using a content provider is available in the <a
|
|
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h2 id="Menus">Adding Action Items to the Activity</h2>
|
|
|
|
<p>Your fragments can contribute action items to the activity's <a
|
|
href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a> (and menu items to the options menu)
|
|
using the callback methods
|
|
{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. In order
|
|
for this method to receive calls, however, you must call {@link
|
|
android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} during the {@link
|
|
android.app.Fragment#onCreate(Bundle) onCreate()} callback in order to indicate that the fragment
|
|
would like to receive a call to {@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater)
|
|
onCreateOptionsMenu()}. Any action or menu items that you add from the fragment are appended to the
|
|
existing
|
|
items for the options menu (including those added by other fragments in the activity). The
|
|
fragment also receives item-selected events with the {@link
|
|
android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} callback method.</p>
|
|
|
|
<p>The {@link android.app.Fragment} class also contains methods to handle context menus. You can
|
|
register a view to provide a context menu with {@link
|
|
android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. When the user opens
|
|
the context menu, the fragment receives a call to {@link
|
|
android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo)
|
|
onCreateContextMenu()}. When the user selects an item, the fragment receives a call to {@link
|
|
android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
|
|
|
|
<p>For more information, see <a href="{@docRoot}guide/topics/ui/menus.html">Creating
|
|
Menus</a> and <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a>.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|