| page.title=Building a Flexible UI |
| |
| trainingnavtop=true |
| |
| @jd:body |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| <h2>This lesson teaches you to</h2> |
| <ol> |
| <li><a href="#AddAtRuntime">Add a Fragment to an Activity at Runtime</a></li> |
| <li><a href="#Replace">Replace One Fragment with Another</a></li> |
| </ol> |
| |
| <h2>You should also read</h2> |
| <ul> |
| <li><a href="{@docRoot}guide/components/fragments.html">Fragments</a></li> |
| <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets and |
| Handsets</a></li> |
| </ul> |
| |
| <h2>Try it out</h2> |
| |
| <div class="download-box"> |
| <a href="http://developer.android.com/shareables/training/FragmentBasics.zip" |
| class="button">Download the sample</a> |
| <p class="filename">FragmentBasics.zip</p> |
| </div> |
| |
| </div> |
| </div> |
| |
| |
| <p>When designing your application to support a wide range of screen sizes, you can reuse your |
| fragments in different layout configurations to optimize the user experience based on the available |
| screen space.</p> |
| |
| <p>For example, on a handset device it might be appropriate to display just one fragment at a time |
| for a single-pane user interface. Conversely, you may want to set fragments side-by-side on a |
| tablet which has a wider screen size to display more information to the user.</p> |
| |
| <img src="{@docRoot}images/training/basics/fragments-screen-mock.png" alt="" /> |
| <p class="img-caption"><strong>Figure 1.</strong> Two fragments, displayed in different |
| configurations for the same activity on different screen sizes. On a large screen, both fragment |
| fit side by side, but on a handset device, only one fragment fits at a time so the fragments must |
| replace each other as the user navigates.</p> |
| |
| <p>The {@link android.support.v4.app.FragmentManager} class provides methods that allow you to add, |
| remove, and replace fragments to an activity at runtime in order to create a dynamic experience.</p> |
| |
| |
| |
| <h2 id="AddAtRuntime">Add a Fragment to an Activity at Runtime</h2> |
| |
| <p>Rather than defining the fragments for an activity in the layout file—as shown in the |
| <a href="creating.html">previous lesson</a> with the {@code <fragment>} element—you can add |
| a fragment to the activity during the activity runtime. This is necessary |
| if you plan to change fragments during the life of the activity.</p> |
| |
| <p>To perform a transaction such as add or |
| remove a fragment, you must use the {@link android.support.v4.app.FragmentManager} to create a |
| {@link android.support.v4.app.FragmentTransaction}, which provides APIs to add, remove, replace, |
| and perform other fragment transactions.</p> |
| |
| <p>If your activity allows the fragments to be removed and replaced, you should add the |
| initial fragment(s) to the activity during the activity's |
| {@link android.app.Activity#onCreate onCreate()} method.</p> |
| |
| <p>An important rule when dealing with fragments—especially those that you add at |
| runtime—is that the fragment must have a container {@link android.view.View} in the layout in |
| which the fragment's layout will reside.</p> |
| |
| <p>The following layout is an alternative to the layout shown in the <a |
| href="creating.html">previous lesson</a> that shows only one fragment at a time. In order to replace |
| one fragment with another, the activity's layout |
| includes an empty {@link android.widget.FrameLayout} that acts as the fragment container.</p> |
| |
| <p>Notice that the filename is the same as the layout file in the previous lesson, but the layout |
| directory does <em>not</em> have the <code>large</code> qualifier, so this layout is used when the |
| device screen is smaller than <em>large</em> because the screen does not fit both fragments at |
| the same time.</p> |
| |
| <p><code>res/layout/news_articles.xml:</code></p> |
| <pre> |
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| android:id="@+id/fragment_container" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" /> |
| </pre> |
| |
| <p>Inside your activity, call {@link |
| android.support.v4.app.FragmentActivity#getSupportFragmentManager()} to get a {@link |
| android.support.v4.app.FragmentManager} using the Support Library APIs. Then call {@link |
| android.support.v4.app.FragmentManager#beginTransaction} to create a {@link |
| android.support.v4.app.FragmentTransaction} and call {@link |
| android.support.v4.app.FragmentTransaction#add add()} to add a fragment.</p> |
| |
| <p>You can perform multiple fragment transaction for the activity using the same {@link |
| android.support.v4.app.FragmentTransaction}. When you're ready to make the changes, you must call |
| {@link android.support.v4.app.FragmentTransaction#commit()}.</p> |
| |
| <p>For example, here's how to add a fragment to the previous layout:</p> |
| |
| <pre> |
| import android.os.Bundle; |
| import android.support.v4.app.FragmentActivity; |
| |
| public class MainActivity extends FragmentActivity { |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.news_articles); |
| |
| // Check that the activity is using the layout version with |
| // the fragment_container FrameLayout |
| if (findViewById(R.id.fragment_container) != null) { |
| |
| // However, if we're being restored from a previous state, |
| // then we don't need to do anything and should return or else |
| // we could end up with overlapping fragments. |
| if (savedInstanceState != null) { |
| return; |
| } |
| |
| // Create an instance of ExampleFragment |
| HeadlinesFragment firstFragment = new HeadlinesFragment(); |
| |
| // In case this activity was started with special instructions from an Intent, |
| // pass the Intent's extras to the fragment as arguments |
| firstFragment.setArguments(getIntent().getExtras()); |
| |
| // Add the fragment to the 'fragment_container' FrameLayout |
| getSupportFragmentManager().beginTransaction() |
| .add(R.id.fragment_container, firstFragment).commit(); |
| } |
| } |
| } |
| </pre> |
| |
| <p>Because the fragment has been added to the {@link android.widget.FrameLayout} container at |
| runtime—instead of defining it in the activity's layout with a {@code <fragment>} |
| element—the activity can remove the fragment and replace it with a different one.</p> |
| |
| |
| |
| <h2 id="Replace">Replace One Fragment with Another</h2> |
| |
| <p>The procedure to replace a fragment is similar to adding one, but requires the {@link |
| android.support.v4.app.FragmentTransaction#replace replace()} method instead of {@link |
| android.support.v4.app.FragmentTransaction#add add()}.</p> |
| |
| <p>Keep in mind that when you perform fragment transactions, such as replace or remove one, it's |
| often appropriate to allow the user to navigate backward and "undo" the change. To allow the user |
| to navigate backward through the fragment transactions, you must call {@link |
| android.support.v4.app.FragmentTransaction#addToBackStack addToBackStack()} before you commit the |
| {@link android.support.v4.app.FragmentTransaction}.</p> |
| |
| <p class="note"><strong>Note:</strong> When you remove or replace a fragment and add the transaction |
| to the back stack, the fragment that is removed is stopped (not destroyed). If the user navigates |
| back to restore the fragment, it restarts. If you <em>do not</em> add the transaction to the back |
| stack, then the fragment is destroyed when removed or replaced.</p> |
| |
| <p>Example of replacing one fragment with another:</p> |
| |
| <pre> |
| // Create fragment and give it an argument specifying the article it should show |
| ArticleFragment newFragment = new ArticleFragment(); |
| Bundle args = new Bundle(); |
| args.putInt(ArticleFragment.ARG_POSITION, position); |
| newFragment.setArguments(args); |
| |
| FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); |
| |
| // Replace whatever is in the fragment_container view with this fragment, |
| // and add the transaction to the back stack so the user can navigate back |
| transaction.replace(R.id.fragment_container, newFragment); |
| transaction.addToBackStack(null); |
| |
| // Commit the transaction |
| transaction.commit(); |
| </pre> |
| |
| <p>The {@link android.support.v4.app.FragmentTransaction#addToBackStack addToBackStack()} method |
| takes an optional string parameter that specifies a unique name for the transaction. The name isn't |
| needed unless you plan to perform advanced fragment operations using the {@link |
| android.support.v4.app.FragmentManager.BackStackEntry} APIs.</p> |
| |
| |
| |
| |