1page.title=构建灵活的界面
2trainingnavtop=true
3page.type=培训
4@jd:body
5
6    <div id="tb-wrapper">
7      <div id="tb">
8        <h2>本课程所教授的内容:</h2>
9    <ol>
10      <li><a href="#AddAtRuntime">在运行时向 Activity 添加 Fragment</a></li>
11      <li><a href="#Replace">用一个 Fragment 替换另一个 Fragment </a></li>
12    </ol>
13
14        <h2>你还应阅读以下内容:</h2>
15        <ul>
16          <li><a href="{@docRoot}guide/components/fragments.html"><code>fragment</code></a></li>
17          <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">支持平板电脑和手机</a></li>
18        </ul>
19
20    <h2>试试以下示例:</h2>
21
22    <div class="download-box">
23     <a href="http://developer.android.com/shareables/training/FragmentBasics.zip" class="button">下载示例</a>
24     <p class="filename">FragmentBasics.zip</p>
25    </div>
26
27      </div>
28    </div>
29
30
31    <p>在设计支持各种屏幕尺寸的应用时,你可以在不同的布局配置中重复使用 Fragment ,以便根据相应的屏幕空间提供更出色的用户体验。</p>
32
33    <p>例如,一次只显示一个 Fragment 可能就很适合手机这种单窗格界面,但在平板电脑上,你可能需要设置并列的 Fragment,因为平板电脑的屏幕尺寸较宽阔,可向用户显示更多信息。</p>
34
35    <img src="{@docRoot}images/training/basics/fragments-screen-mock.png" alt="" />
36    <p class="img-caption"><strong>图 1:</strong> 两个 Fragment,显示在不同尺寸屏幕上同一 Activity 的不同配置中。在较宽阔的屏幕上,两个 Fragment 可并列显示;在手机上,一次只能显示一个 Fragment,因此必须在用户导航时更换 Fragment。</p>
37
38    <p>利用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.html">FragmentManager</a></code> 类提供的方法,你可以在运行时添加、移除和替换 Activity 中的 Fragment,以便为用户提供一种动态体验。</p>
39
40
41
42    <h2 id="AddAtRuntime">在运行时向 Activity 添加 Fragment</h2>
43
44    <p>你可以在 Activity 运行时向其添加 Fragment,而不用像<a href="creating.html">上一课</a>中介绍的那样,使用 <code>&lt;fragment&gt;</code> 元素在布局文件中为 Activity 定义 Fragment。如果你打算在 Activity 运行周期内更改 Fragment,就必须这样做。</p>
45
46    <p>要执行添加或移除 Fragment 等事务,你必须使用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.html">FragmentManager</a></code> 创建一个 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html">FragmentTransaction</a></code>,后者可提供用于执行添加、移除、替换以及其他 Fragment 事务的 API。</p>
47
48    <p>如果 Activity 中的 Fragment 可以移除和替换,你应在调用 Activity 的 <code><a href="{@docRoot}reference/android/app/Activity.html#onCreate(android.os.Bundle)">onCreate()</a></code> 方法期间为 Activity 添加初始 Fragment(s)。</p>
49
50    <p>在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记以下重要规则:必须在布局中为 Fragment 提供 <code><a href="{@docRoot}reference/android/view/View.html">View</a></code> 容器,以便保存 Fragment 的布局。</p>
51
52    <p>下面是<a href="creating.html">上一课</a>所示布局的替代布局,这种布局一次只会显示一个 Fragment。要用一个 Fragment 替换另一个 Fragment, Activity 的布局中需要包含一个作为 Fragment 容器的空 <code><a href="{@docRoot}reference/android/widget/FrameLayout.html">FrameLayout</a></code>。</p>
53
54    <p><em></em>请注意,该文件名与上一课中布局文件的名称相同,但布局目录没有 <code>large</code> 这一限定符。因此,此布局会在设备屏幕小于“large”的情况下使用,原因是尺寸较小的屏幕不适合同时显示两个 Fragment。<em></em></p>
55
56    <p><code>res/layout/news_articles.xml:</code></p>
57    <pre>
58    &lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
59        android:id="@+id/fragment_container"
60        android:layout_width="match_parent"
61        android:layout_height="match_parent" /&gt;
62    </pre>
63
64    <p>在 Activity 内部,使用 Support Library API 调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentActivity.html#getSupportFragmentManager()">getSupportFragmentManager()</a></code> 以获取 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.html">FragmentManager</a></code>,然后调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.html#beginTransaction()">beginTransaction()</a></code> 创建 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html">FragmentTransaction</a></code>,同时调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#add(android.support.v4.app.Fragment, java.lang.String)">add()</a></code> 添加 Fragment。</p>
65
66    <p>你可以使用同一个 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html">FragmentTransaction</a></code> 对 Activity 执行多 Fragment 事务。当你准备好进行更改时,必须调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#commit()">commit()</a></code>。</p>
67
68    <p>例如,下面介绍了如何为上述布局添加 Fragment :</p>
69
70    <pre>
71    import android.os.Bundle;
72    import android.support.v4.app.FragmentActivity;
73
74    public class MainActivity extends FragmentActivity {
75        &amp;Override
76        public void onCreate(Bundle savedInstanceState) {
77            super.onCreate(savedInstanceState);
78            setContentView(R.layout.news_articles);
79
80            // 确认 Activity 使用的布局版本包含
81            // fragment_container FrameLayout
82            if (findViewById(R.id.fragment_container) != null) {
83
84                // 不过,如果我们要从先前的状态还原,
85                // 则无需执行任何操作而应返回
86                // 否则就会得到重叠的 Fragment 。
87                if (savedInstanceState != null) {
88                    return;
89                }
90
91                // 创建一个要放入 Activity 布局中的新 Fragment
92                HeadlinesFragment firstFragment = new HeadlinesFragment();
93
94                // 如果此 Activity 是通过 Intent 发出的特殊指令来启动的,
95                // 请将该 Intent 的 extras 以参数形式传递给该 Fragment
96                firstFragment.setArguments(getIntent().getExtras());
97
98                // 将该 Fragment 添加到“fragment_container”FrameLayout 中
99                getSupportFragmentManager().beginTransaction()
100                        .add(R.id.fragment_container, firstFragment).commit();
101            }
102        }
103    }
104    </pre>
105
106    <p>由于该 Fragment 已在运行时添加到 <code><a href="{@docRoot}reference/android/widget/FrameLayout.html">FrameLayout</a></code> 容器中,而不是在 Activity 布局中通过 <code>&lt;fragment&gt;</code> 元素进行定义,因此该 Activity 可以移除和替换这个 Fragment 。</p>
107
108
109
110    <h2 id="Replace">用一个 Fragment 替换另一个 Fragment </h2>
111
112    <p>替换 Fragment 的步骤与添加 Fragment 的步骤相似,但需要调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#replace(int, android.support.v4.app.Fragment)">replace()</a></code> 方法,而非 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#add(android.support.v4.app.Fragment, java.lang.String)">add()</a></code>。</p>
113
114    <p>请注意,当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#addToBackStack(java.lang.String)">addToBackStack()</a></code>,然后再执行 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html">FragmentTransaction</a></code>。</p>
115
116    <p class="note"><strong>注意</strong>:当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会停止(而不是销毁)。如果用户向后导航,还原该 Fragment,它会重新启动。如果你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁<em></em>。</p>
117
118    <p>替换 Fragment 的示例:</p>
119
120    <pre>
121    // 创建 Fragment 并为其添加一个参数,用来指定应显示的文章
122    ArticleFragment newFragment = new ArticleFragment();
123    Bundle args = new Bundle();
124    args.putInt(ArticleFragment.ARG_POSITION, position);
125    newFragment.setArguments(args);
126
127    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
128
129    // 将 fragment_container <code>View</code> 中的内容替换为此 Fragment ,
130    // 然后将该事务添加到返回堆栈,以便用户可以向后导航
131    transaction.replace(R.id.fragment_container, newFragment);
132    transaction.addToBackStack(null);
133
134    // 执行事务
135    transaction.commit();
136    </pre>
137
138    <p><code><a href="{@docRoot}reference/android/support/v4/app/FragmentTransaction.html#addToBackStack(java.lang.String)">addToBackStack()</a></code>  方法可接受可选的字符串参数,来为事务指定独一无二的名称。除非你打算使用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.BackStackEntry.html">FragmentManager.BackStackEntry</a></code> API 执行高级 Fragment 操作,否则无需使用此名称。</p>
139
140