在設計支持各類屏幕尺寸的應用時,你能夠在不一樣的佈局配置中重複使用 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 操做,不然無需使用此名稱。