這一節的主要內容
1、在運行時添加一個fragment到Activity
2、替換fragment
為了適應不同大小的屏幕,我們可以根據屏幕的大小動態地在不同的布局文件中重用fragment。比如,對于在手機上,我們可能就只能顯示一個fragment,而在平板電腦上我們就可以并列地在界面上顯示兩個fragment,以便顯示更多的信息。
圖1.同一個Activity中的兩個fragment在大小不同的屏幕上的顯示效果。在大屏幕上,兩個fragment并列顯示。而在小屏幕上,同一時間只顯示一個fragment,另一個fragment當用戶需要的時候才顯示。
在Activity運行時添加fragment
除了在XML配置文件中定義一個fragment--像上一節我們講到的使用<fragment>
元素--你也可以在activity運行時向他添加一個fragment。如果你打算在activity存活的時候,改變fragment,這就很有必要。
為了實現事務性操作如添加或刪除一個fragment,我們必須使用FragmentManager來創建一個
FragmentTransaction。我們可以通過
FragmentTransaction 提供的API實現添加、刪除、替換和其他的fragment事務性操作。
如果你要允許activity中的fragment可以被刪除或者替換,那你就應該在activity的
onCreate()
方法中初始化fragment。
使用Fragment很重要的一點是--特別是當你想要在運行時添加fragment--就是fragment必須裝在布局中的一個容器View里面.
下面的布局方式相對于上一節所講的不能在運行時被修改的fragment布局方式是另一種選擇。為了可以將布局中的fragment替換成另一個,在Activity中必須有一個空的
FrameLayout,以便作為fragment的容器。
注意下面的文件名跟上一節的布局文件的名字一樣,但是布局文件的路徑中沒有
large限定詞,所以這個布局使用在比large尺寸更小的屏幕上的,因為屏幕的大小不足以同時將所有的fragment放進去。
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里面,調用getSupportFragmentManager()來獲取兼容庫(the Support Library)中的
FragmentManager。然后調用
beginTransaction()
來創建一個FragmentTransaction
,最后調用 add()
增加一個fragment.
你可以在一個Activity里面同時進行多個fragment事務性操作,使用同一個
FragmentTransaction。當你已經沒有更多要修改的東西時,你可以調用
commit()讓操作生效。
下面的例子展示的是怎么向前面的布局文件添加一個fragment:
package com.bang.testfragment; 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中的額外信息作為參數傳遞給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的過程跟添加fragment的過程差不多,只不過需要用replace()方法而不是add()
.
要記住當我們做一些跟fragment有關的事務性操作時,比如替換或刪除某個fragment,通常用戶可能會想回退或者撤銷原來的操作。為了允許用戶撤銷操作,你必須在準備提交FragmentTransaction
前調用addToBackStack()。
注意:當你刪除或替換一個fragment并將添加fragment事務到back stack,被刪除的其實是停止了(而不是銷毀)。如果用戶為了恢復fragment而回退,它就會重新啟動。如果你沒有將fragment事務添加到back stack中,那么當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替換在fragment_container中的任何東西 // 并將事務添加到back stack 中,以便用戶可以回退,恢復之前的操作 transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // 提交事務 transaction.commit();
addToBackStack()
方法接受一個用來做事務名稱的string類型的參數。這個參數不是必須的,除非你打算使用用到FragmentManager.BackStackEntry
APIs去做一些高級的fragment操作。
文章列表