當設計程序來支持各類不同的屏幕尺寸時,能夠在不一樣的佈局中重用fragment來根據可用的屏幕大小來優化用戶體驗。html
例如,在手機上可能使用一個fragment來使用單窗口用戶體驗比較合適。可是,你可能想在平板上邊靠邊的設置兩個fragment由於有更寬的屏幕向用戶展現更多信息。java
圖1.兩個fragment,同一個activity在不一樣的屏幕大小上的不一樣展示形式。在大屏幕上,兩個fragment邊靠邊,可是在手機設備上,一次只顯示一個fragment所以fragment在用戶切換的時候替換另外一個。android
爲了建立動態的體驗, FragmentManager類提供了方法能夠在運行時添加,刪除,替換activity中的fragment。app
在運行時向activity添加fragmentide
不單單能夠在activity佈局文件中定義fragment(前面介紹了使用<fragment>元素),也能夠在activity運行時加入fragment。若是計劃在activity運行時改變fragment,這個頗有必要。佈局
要處理添加刪除fragment,可使用FragmentManager來建立一個FragmentTransation,它提供了API來添加,替換和fragment的其餘事務。優化
若是activity容許fragment刪除或者替換,應該在activity的onCreate()方法中添加fragment的初始化信息。spa
處理fragment有一個重要的規則,特別是在運行時添加的fragment:fragment在佈局中必須有一個View容器。設計
下面的佈局是上一篇中佈局的一個變形,這裏一次只顯示一個fragment。爲了用一個fragment替換另外一個,這個activity的佈局包含一個空的FrameLayout做爲fragment的容器。code
這個文件名和前面一篇中佈局的文件名是同樣的,可是佈局文件夾沒有large標識,因此這個佈局使用在小屏幕上由於小屏幕不須要同時顯示兩個fragment。
res/layout/news_articles.xml:
1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/fragment_container" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" />
在activity中,使用Support Library中的API getSupportFragmentManager()來得到FragmentManager.而後調用beginTransaction()來建立一個FragmentTransaction再調用add()添加一個fragment。
可使用一個FragmentTransaction來處理多個activity的fragment rransaction。當準備好執行這些改變後,調用commit()。
例如,這裏展現瞭如何把fragment加到前一個佈局上:
1 import android.os.Bundle; 2 import android.support.v4.app.FragmentActivity; 3 4 public class MainActivity extends FragmentActivity { 5 @Override 6 public void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.news_articles); 9 10 11 //檢查activity的佈局是使用fragment_container FrameLayout的版本 12 if (findViewById(R.id.fragment_container) != null) { 13 14 // 可是,若是是從前一個狀態恢復的話 15 // 咱們不須要作任何事情,直接返回就好了,不然就會重疊fragments。 16 if (savedInstanceState != null) { 17 return; 18 } 19 20 //建立一個Fragment實例 21 HeadlinesFragment firstFragment = new HeadlinesFragment(); 22 23 //有可能activity是從Intent中的特殊指令建立的, 24 //把Intent的extras當參數傳遞給fragment 25 firstFragment.setArguments(getIntent().getExtras()); 26 27 // 把fragment加入到'fragment_container' FrameLayout 28 getSupportFragmentManager().beginTransaction() 29 .add(R.id.fragment_container, firstFragment).commit(); 30 } 31 } 32 }
由於fragment是在運行時加入到FrameLayout的(不是在activity的佈局文件中用<fragment>定義的),activity就能夠移出這個fragment而後用一個不一樣的替換它。
用一個fragment替換另外一個
換掉一個fragment的方法和添加一個類似,可是須要使用replace()方法,而不是add()。
記住當執行fragment切換時,例如添加或者刪除,常常要容許用戶切換回去來恢復這些改變。爲了容許用戶在fragment切換時切換回去,應該在提交FragmentTransaction以前調用addToBackStack()。
注意:當移除或者替換一個fragment而後加到切換的返回堆棧中時,被移除的fragment是Stopped狀態(並非Destroyed)。若是用戶切換回去來恢復fragment,它就重啓。若是沒有把它加到返回堆棧中,fragment被移除或者替換時就銷燬了。
用一個fragment替換另外一個的例子:
1 //建立一個fragment,而後把應該展現的文章的參數傳給它 2 ArticleFragment newFragment = new ArticleFragment(); 3 Bundle args = new Bundle(); 4 args.putInt(ArticleFragment.ARG_POSITION, position); 5 newFragment.setArguments(args); 6 7 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 8 9 //用這個fragment替換掉fragment_container view 中的東西, 10 //而後把transaction加到返回堆棧中,這樣用戶就能夠切換回去了 11 transaction.replace(R.id.fragment_container, newFragment); 12 transaction.addToBackStack(null); 13 14 //提交transaction 15 transaction.commit();
addToBackStack()方法帶一個可選的字符串參數,用來指定一個惟一的transaction名字。這個名字並非必需的除非須要用FragmentManager.BackStackEntryAPI的一些特使操做。