blob: d07daf47a2d58efbf1e80494737597a29fbfb52f [file] [log] [blame]
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&mdash;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&mdash;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 &lt;fragment&gt;} 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&mdash;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 {
&#64;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&mdash;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>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"&gt;
&lt;fragment android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;fragment android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>The {@code &lt;fragment&gt;} 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 &lt;fragment&gt;} 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
&lt;fragment&gt;}</li>
<li>Supply the {@code android:tag} attribute with a unique string ID, in the {@code
&lt;fragment&gt;}</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.FragmentManager} using {@link
android.app.FragmentManager#openTransaction()}. 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();
getFragmentManager().openTransaction().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>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" &gt;
&lt;TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello" /&gt;
&lt;TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello" /&gt;
&lt;/LinearLayout&gt;
</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 {
&#64;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>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"&gt;
&lt;fragment android:name="com.example.SimpleFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;fragment android:name="com.example.SimpleFragment"
android:id="@+id/viewer"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;/LinearLayout&gt;
</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 FragmentManager with {@link
android.app.FragmentManager#openTransaction}.</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 = getFragmentManager().openTransaction();
// 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&mdash;but only while the activity is
resumed (while it is in the foreground)&mdash;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.FragmentManager#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&mdash;one to show a list of
articles (fragment A) and another to display an article (fragment B)&mdash;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 {
...
&#64;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 {
...
&#64;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>