197 lines
8.5 KiB
Plaintext
197 lines
8.5 KiB
Plaintext
page.title=Building a Flexible UI
|
|
parent.title=Building a Dynamic UI with Fragments
|
|
parent.link=index.html
|
|
|
|
trainingnavtop=true
|
|
previous.title=Create a Fragment
|
|
previous.link=creating.html
|
|
next.title=Communicating with Other Fragments
|
|
next.link=communicating.html
|
|
|
|
@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>
|
|
|
|
|
|
|
|
|