在设计支持各类屏幕尺寸的应用时,你能够在不一样的布局配置中重复使用 Fragment ,以便根据相应的屏幕空间提供更出色的用户体验。html
例如,一次只显示一个 Fragment 可能就很适合手机这种单窗格界面,但在平板电脑上,你可能须要设置并列的 Fragment,由于平板电脑的屏幕尺寸较宽阔,可向用户显示更多信息。java
图 1: 两个 Fragment,显示在不一样尺寸屏幕上同一 Activity 的不一样配置中。在较宽阔的屏幕上,两个 Fragment 可并列显示;在手机上,一次只能显示一个 Fragment,所以必须在用户导航时更换 Fragment。android
利用 FragmentManager
类提供的方法,你能够在运行时添加、移除和替换 Activity 中的 Fragment,以便为用户提供一种动态体验。app
你能够在 Activity 运行时向其添加 Fragment,而不用像上一课中介绍的那样,使用 <fragment>
元素在布局文件中为 Activity 定义 Fragment。若是你打算在 Activity 运行周期内更改 Fragment,就必须这样作。ide
要执行添加或移除 Fragment 等事务,你必须使用 FragmentManager
建立一个 FragmentTransaction
,后者可提供用于执行添加、移除、替换以及其余 Fragment 事务的 API。布局
若是 Activity 中的 Fragment 能够移除和替换,你应在调用 Activity 的 onCreate()
方法期间为 Activity 添加初始 Fragment(s)。spa
在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记如下重要规则:必须在布局中为 Fragment 提供 View
容器,以便保存 Fragment 的布局。设计
下面是上一课所示布局的替代布局,这种布局一次只会显示一个 Fragment。要用一个 Fragment 替换另外一个 Fragment, Activity 的布局中须要包含一个做为 Fragment 容器的空 FrameLayout
。code
请注意,该文件名与上一课中布局文件的名称相同,但布局目录没有 large
这一限定符。所以,此布局会在设备屏幕小于“large”的状况下使用,缘由是尺寸较小的屏幕不适合同时显示两个 Fragment。xml
res/layout/news_articles.xml:
<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" />
在 Activity 内部,使用 Support Library API 调用 getSupportFragmentManager()
以获取 FragmentManager
,而后调用 beginTransaction()
建立 FragmentTransaction
,同时调用 add()
添加 Fragment。
你可使用同一个 FragmentTransaction
对 Activity 执行多 Fragment 事务。当你准备好进行更改时,必须调用 commit()
。
例如,下面介绍了如何为上述布局添加 Fragment :
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);
// 确认 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();
}
}
}
因为该 Fragment 已在运行时添加到 FrameLayout
容器中,而不是在 Activity 布局中经过 <fragment>
元素进行定义,所以该 Activity 能够移除和替换这个 Fragment 。
替换 Fragment 的步骤与添加 Fragment 的步骤类似,但须要调用 replace()
方法,而非 add()
。
请注意,当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所作更改。要经过 Fragment 事务容许用户向后导航,你必须调用 addToBackStack()
,而后再执行 FragmentTransaction
。
注意:当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会中止(而不是销毁)。若是用户向后导航,还原该 Fragment,它会从新启动。若是你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁。
替换 Fragment 的示例:
// 建立 Fragment 并为其添加一个参数,用来指定应显示的文章
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 将 fragment_container 中的内容替换为此 Fragment ,
// 而后将该事务添加到返回堆栈,以便用户能够向后导航
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// 执行事务
transaction.commit();
View
addToBackStack()
方法可接受可选的字符串参数,来为事务指定独一无二的名称。除非你打算使用 FragmentManager.BackStackEntry
API 执行高级 Fragment 操做,不然无需使用此名称。