在執行階段,FragmentManager
可根據使用者互動內容來新增、移除、取代及執行其他包含片段的動作。您修訂的每組片段變更都稱為「交易」,且您可以使用 FragmentTransaction
類別提供的 API 指定交易過程中要執行的作業。您可以將多個動作分入單一交易。舉例來說,某個交易可新增或取代多個片段。如要在同一畫面上顯示多個同層片段 (例如分割檢視),這種分組做法就會很實用。
您可以將每個交易儲存至由 FragmentManager
管理的返回堆疊,讓使用者透過片段變更返回瀏覽 (原理類似瀏覽先前的活動)。
您可以呼叫 beginTransaction()
來取得 FragmentManager
的 FragmentTransaction
例項,如以下範例所示:
Kotlin
val fragmentManager = ... val fragmentTransaction = fragmentManager.beginTransaction()
Java
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
每個 FragmentTransaction
的最終呼叫都必須修訂交易。commit()
呼叫會指示 FragmentManager
,說明所有作業都已新增至交易。
Kotlin
val fragmentManager = ... // The fragment-ktx module provides a commit block that automatically // calls beginTransaction and commit for you. fragmentManager.commit { // Add operations here }
Java
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // Add operations here fragmentTransaction.commit();
允許重新排序片段狀態變更
每個 FragmentTransaction
都應使用 setReorderingAllowed(true)
:
Kotlin
supportFragmentManager.commit { ... setReorderingAllowed(true) }
Java
FragmentManager fragmentManager = ... fragmentManager.beginTransaction() ... .setReorderingAllowed(true) .commit();
為了提供行為相容性,系統預設不會啟用重新排序標記。但如果想讓 FragmentManager
正確執行 FragmentTransaction
(尤其是當其在返回堆疊中運作,並會執行動畫和轉換時),就必須啟用這個標記。啟用這個標記後,如果有多個共同執行的交易,任何中繼片段 (例如新增後立即遭到取代的片段) 都一定不會經歷生命週期變更,系統也一定不會執行這些片段的動畫或轉換。請注意,如果啟用這個標記,交易的初始執行作業和透過 popBackStack()
進行的交易反轉作業都會受到影響。
新增和移除片段
如要將片段新增至 FragmentManager
,請針對交易呼叫 add()
。這個方法會接收片段「容器」的 ID,以及待新增片段的類別名稱。新增的片段會移至 RESUMED
狀態。我們強烈建議您將「容器」視為屬於檢視區塊階層一部分的 FragmentContainerView
。
如要從主機中移除片段,請呼叫 remove()
,傳入透過 findFragmentById()
或 findFragmentByTag()
從片段管理員擷取的片段例項。如果片段的檢視區塊先前已新增至容器,系統會在這個階段將該檢視區塊從容器中移除。遭移除的片段會移至 DESTROYED
狀態。
使用 replace()
,將容器中現有的片段取代為您提供的新片段類別例項。呼叫 replace()
就等同於呼叫容器中含有片段的 remove()
並在該容器中新增片段。
以下程式碼片段說明如何將某個片段取代為其他片段:
Kotlin
// Create new fragment val fragmentManager = // ... // Create and commit a new transaction fragmentManager.commit { setReorderingAllowed(true) // Replace whatever is in the fragment_container view with this fragment replace<ExampleFragment>(R.id.fragment_container) }
Java
// Create new fragment and transaction FragmentManager fragmentManager = ... FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.setReorderingAllowed(true); // Replace whatever is in the fragment_container view with this fragment transaction.replace(R.id.fragment_container, ExampleFragment.class, null); // Commit the transaction transaction.commit();
在這個範例中,ExampleFragment
的新例項會取代目前在版面配置容器中由 R.id.fragment_container
識別的片段 (如果有的話)。
根據預設,在 FragmentTransaction
中所做的變更不會新增至返回堆疊。如要儲存這些變更,您可以針對 FragmentTransaction
呼叫 addToBackStack()
。詳情請參閱「片段管理員」一文。
修訂作業為非同步性質
呼叫 commit()
後,系統不會立即執行交易,而會安排盡快在主要 UI 執行緒中執行交易。不過,您可以視需要呼叫 commitNow()
,立即在 UI 執行緒中執行片段交易。
請注意,commitNow
與 addToBackStack
不相容。或者,您也可以呼叫 executePendingTransactions()
,藉此執行已由 commit()
提交但尚未執行的所有待處理 FragmentTransactions
。這個做法與 addToBackStack
相容。
對大多數用途而言,您只要使用 commit()
即可。
作業順序相當重要
FragmentTransaction
中的作業執行順序相當重要,尤其是使用 setCustomAnimations()
時。這個方法會將特定動畫套用至後續所有的片段作業。
Kotlin
supportFragmentManager.commit { setCustomAnimations(enter1, exit1, popEnter1, popExit1) add<ExampleFragment>(R.id.container) // gets the first animations setCustomAnimations(enter2, exit2, popEnter2, popExit2) add<ExampleFragment>(R.id.container) // gets the second animations }
Java
getSupportFragmentManager().beginTransaction() .setCustomAnimations(enter1, exit1, popEnter1, popExit1) .add(R.id.container, ExampleFragment.class, null) // gets the first animations .setCustomAnimations(enter2, exit2, popEnter2, popExit2) .add(R.id.container, ExampleFragment.class, null) // gets the second animations .commit()
限制片段的生命週期
針對交易範圍內新增的個別片段,FragmentTransactions
可能會影響其生命週期狀態。建立 FragmentTransaction
時,setMaxLifecycle()
會設定特定片段的狀態上限。例如,ViewPager2
會使用 setMaxLifecycle()
將螢幕外片段限制為 STARTED
狀態。
顯示和隱藏片段的檢視區塊
使用 FragmentTransaction
方法 show()
和 hide()
來顯示/隱藏已新增至容器的片段檢視區塊。這些方法會改變片段檢視區塊的顯示設定,而「不會」影響片段的生命週期。
雖然您不需要使用片段交易來切換片段中各個檢視區塊的顯示設定,但如果您想將顯示狀態變更為與返回堆疊中的交易有關聯,就很適合使用這些方法。
附加和卸離片段
FragmentTransaction
方法 detach()
會將片段從 UI 卸離,並刪除其檢視區塊階層。片段會繼續處於其在返回堆疊中的狀態 (STOPPED
)。這表示片段雖然已從 UI 中移除,但仍是由片段管理員所管理。
attach()
方法會重新附加先前已卸離的片段。這會導致系統重新建立檢視區塊階層、將階層附加至 UI 並顯示該階層。
系統會將 FragmentTransaction
視為一組不可拆分的作業,因此如果在同一交易中針對相同片段例項同時呼叫 detach
和 attach
,兩者實際上會互相抵銷,避免系統刪除並立即重新建立片段的 UI。如要卸離並立即重新附加某個片段,請使用不同的交易並以 executePendingOperations()
分隔 (如有使用 commit()
)。