summaryrefslogtreecommitdiffstats
path: root/docs/html-intl/intl/zh-cn/training/basics/fragments/fragment-ui.jd
blob: 51a4e278e5bc3bae6892877d668210f2e8c71d7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
page.title=构建灵活的界面
trainingnavtop=true
page.type=培训
@jd:body

    <div id="tb-wrapper">
      <div id="tb"> 
        <h2>本课程所教授的内容:</h2>
    <ol>
      <li><a href="#AddAtRuntime">在运行时向 Activity 添加 Fragment</a></li>
      <li><a href="#Replace">用一个 Fragment 替换另一个 Fragment </a></li>
    </ol>

        <h2>你还应阅读以下内容:</h2>
        <ul>
          <li><a href="{@docRoot}guide/components/fragments.html"><code>fragment</code></a></li>
          <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">支持平板电脑和手机</a></li>
        </ul>

    <h2>试试以下示例:</h2>

    <div class="download-box">
     <a href="http://developer.android.com/shareables/training/FragmentBasics.zip" class="button">下载示例</a>
     <p class="filename">FragmentBasics.zip</p>
    </div>

      </div>
    </div>


    <p>在设计支持各种屏幕尺寸的应用时,你可以在不同的布局配置中重复使用 Fragment ,以便根据相应的屏幕空间提供更出色的用户体验。</p>

    <p>例如,一次只显示一个 Fragment 可能就很适合手机这种单窗格界面,但在平板电脑上,你可能需要设置并列的 Fragment,因为平板电脑的屏幕尺寸较宽阔,可向用户显示更多信息。</p>

    <img src="{@docRoot}images/training/basics/fragments-screen-mock.png" alt="" />
    <p class="img-caption"><strong>图 1:</strong> 两个 Fragment,显示在不同尺寸屏幕上同一 Activity 的不同配置中。在较宽阔的屏幕上,两个 Fragment 可并列显示;在手机上,一次只能显示一个 Fragment,因此必须在用户导航时更换 Fragment。</p>

    <p>利用 <code><a href="{@docRoot}reference/android/support/v4/app/FragmentManager.html">FragmentManager</a></code> 类提供的方法,你可以在运行时添加、移除和替换 Activity 中的 Fragment,以便为用户提供一种动态体验。</p>



    <h2 id="AddAtRuntime">在运行时向 Activity 添加 Fragment</h2> 

    <p>你可以在 Activity 运行时向其添加 Fragment,而不用像<a href="creating.html">上一课</a>中介绍的那样,使用 <code>&lt;fragment&gt;</code> 元素在布局文件中为 Activity 定义 Fragment。如果你打算在 Activity 运行周期内更改 Fragment,就必须这样做。</p>

    <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>

    <p>如果 Activity 中的 Fragment 可以移除和替换,你应在调用 Activity 的 <code><a href="{@docRoot}reference/android/app/Activity.html#onCreate(android.os.Bundle)">onCreate()</a></code> 方法期间为 Activity 添加初始 Fragment(s)。</p>

    <p>在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记以下重要规则:必须在布局中为 Fragment 提供 <code><a href="{@docRoot}reference/android/view/View.html">View</a></code> 容器,以便保存 Fragment 的布局。</p>

    <p>下面是<a href="creating.html">上一课</a>所示布局的替代布局,这种布局一次只会显示一个 Fragment。要用一个 Fragment 替换另一个 Fragment, Activity 的布局中需要包含一个作为 Fragment 容器的空 <code><a href="{@docRoot}reference/android/widget/FrameLayout.html">FrameLayout</a></code>。</p>

    <p><em></em>请注意,该文件名与上一课中布局文件的名称相同,但布局目录没有 <code>large</code> 这一限定符。因此,此布局会在设备屏幕小于“large”的情况下使用,原因是尺寸较小的屏幕不适合同时显示两个 Fragment。<em></em></p>

    <p><code>res/layout/news_articles.xml:</code></p>
    <pre>
    &lt;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" /&gt;
    </pre>

    <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>

    <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>

    <p>例如,下面介绍了如何为上述布局添加 Fragment :</p>

    <pre>
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;

    public class MainActivity extends FragmentActivity {
        &amp;Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.news_articles);

            // 确认 Activity 使用的布局版本包含
            // fragment_container FrameLayout
            if (findViewById(R.id.fragment_container) != null) {

                // 不过,如果我们要从先前的状态还原,
                // 则无需执行任何操作而应返回
                // 否则就会得到重叠的 Fragment 。
                if (savedInstanceState != null) {
                    return;
                }

                // 创建一个要放入 Activity 布局中的新 Fragment 
                HeadlinesFragment firstFragment = new HeadlinesFragment();

                // 如果此 Activity 是通过 Intent 发出的特殊指令来启动的,
                // 请将该 Intent 的 extras 以参数形式传递给该 Fragment 
                firstFragment.setArguments(getIntent().getExtras());

                // 将该 Fragment 添加到“fragment_container”FrameLayout 中
                getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_container, firstFragment).commit();
            }
        }
    }
    </pre>

    <p>由于该 Fragment 已在运行时添加到 <code><a href="{@docRoot}reference/android/widget/FrameLayout.html">FrameLayout</a></code> 容器中,而不是在 Activity 布局中通过 <code>&lt;fragment&gt;</code> 元素进行定义,因此该 Activity 可以移除和替换这个 Fragment 。</p>



    <h2 id="Replace">用一个 Fragment 替换另一个 Fragment </h2>

    <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>

    <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>

    <p class="note"><strong>注意</strong>:当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会停止(而不是销毁)。如果用户向后导航,还原该 Fragment,它会重新启动。如果你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁<em></em>。</p>

    <p>替换 Fragment 的示例:</p>

    <pre>
    // 创建 Fragment 并为其添加一个参数,用来指定应显示的文章
    ArticleFragment newFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putInt(ArticleFragment.ARG_POSITION, position);
    newFragment.setArguments(args);

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // 将 fragment_container <code>View</code> 中的内容替换为此 Fragment ,
    // 然后将该事务添加到返回堆栈,以便用户可以向后导航
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);

    // 执行事务
    transaction.commit();
    </pre>

    <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>