diff options
author | Scott Main <smain@google.com> | 2010-08-17 11:48:09 -0700 |
---|---|---|
committer | Scott Main <smain@google.com> | 2010-11-18 12:42:47 -0800 |
commit | c18b534585741e1cc6c8328f7761c906f58c2684 (patch) | |
tree | f20c941b05db8e6a0c2d77297a4cfb9509c7c103 /docs | |
parent | 3d1c5a27884ef01772b187ff250daadb7678572e (diff) | |
download | frameworks_base-c18b534585741e1cc6c8328f7761c906f58c2684.zip frameworks_base-c18b534585741e1cc6c8328f7761c906f58c2684.tar.gz frameworks_base-c18b534585741e1cc6c8328f7761c906f58c2684.tar.bz2 |
new docs for fragments
Change-Id: Ia21a4c844d475a743399d25dfe43f916d423258c
Diffstat (limited to 'docs')
-rw-r--r-- | docs/html/guide/guide_toc.cs | 3 | ||||
-rw-r--r-- | docs/html/guide/topics/fragments/index.jd | 648 | ||||
-rw-r--r-- | docs/html/guide/topics/manifest/activity-element.jd | 3 | ||||
-rw-r--r-- | docs/html/guide/topics/manifest/application-element.jd | 8 | ||||
-rw-r--r-- | docs/html/images/activity_fragment_lifecycle.png | bin | 0 -> 50826 bytes | |||
-rw-r--r-- | docs/html/images/fragment_lifecycle.png | bin | 0 -> 69715 bytes |
6 files changed, 660 insertions, 2 deletions
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 545807e..3cc1806 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -196,6 +196,9 @@ </li> </ul> <ul> + <li><a href="<?cs var:toroot ?>guide/topics/fragments/index.html"> + <span class="en">Fragments</span> + </a> <span class="new">new!</span></li> <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html"> <span class="en">Graphics</span> diff --git a/docs/html/guide/topics/fragments/index.jd b/docs/html/guide/topics/fragments/index.jd new file mode 100644 index 0000000..ce10ef7 --- /dev/null +++ b/docs/html/guide/topics/fragments/index.jd @@ -0,0 +1,648 @@ +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(newFragment, R.id.myfragment); +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> + + + + + + diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index e030a4c..2648cb7 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -290,7 +290,8 @@ activity is ignored. The activity is not re-parented, but destroyed. <dd>An icon representing the activity. The icon is displayed to users when a representation of the activity is required on-screen. For example, icons for activities that initiate tasks are displayed in the launcher window. -The icon is often accompanied by a label (see the {@code label} attribute). +The icon is often accompanied by a label (see the <a href="#label">{@code +android:label}</a> attribute). </p> <p> diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd index 9ac07fd..1fadc6e 100644 --- a/docs/html/guide/topics/manifest/application-element.jd +++ b/docs/html/guide/topics/manifest/application-element.jd @@ -12,6 +12,7 @@ page.title=<application> android:<a href="#icon">icon</a>="<i>drawable resource</i>" android:<a href="#killrst">killAfterRestore</a>=["true" | "false"] android:<a href="#label">label</a>="<i>string resource</i>" + android:<a href="#logo">logo</a>="<i>drawable resource</i>" android:<a href="#space">manageSpaceActivity</a>="<i>string</i>" android:<a href="#nm">name</a>="<i>string</i>" android:<a href="#prmsn">permission</a>="<i>string</i>" @@ -121,7 +122,7 @@ each of the application's components. See the individual <p> This attribute must be set as a reference to a drawable resource containing -the image definition. There is no default icon. +the image (for example {@code "@drawable/icon"}). There is no default icon. </p></dd> <dt><a name="killrst"></a>{@code android:killAfterRestore}</dt> @@ -154,6 +155,11 @@ However, as a convenience while you're developing the application, it can also be set as a raw string. </p></dd> +<dt><a name="logo"></a>{@code android:logo}</dt> +<dd>A logo for the application as whole, and the default logo for activities. +<p>This attribute must be set as a reference to a drawable resource containing +the image (for example {@code "@drawable/logo"}). There is no default logo.</p></dd> + <dt><a name="space"></a>{@code android:manageSpaceActivity}</dt> <dd>The fully qualified name of an Activity subclass that the system can launch to let users manage the memory occupied by the application diff --git a/docs/html/images/activity_fragment_lifecycle.png b/docs/html/images/activity_fragment_lifecycle.png Binary files differnew file mode 100644 index 0000000..156aa40 --- /dev/null +++ b/docs/html/images/activity_fragment_lifecycle.png diff --git a/docs/html/images/fragment_lifecycle.png b/docs/html/images/fragment_lifecycle.png Binary files differnew file mode 100644 index 0000000..ce9d395 --- /dev/null +++ b/docs/html/images/fragment_lifecycle.png |