建立片段
若要建立 Fragment,類別必須繼承自 Android.App.Fragment
,然後覆寫 OnCreateView
方法。 OnCreateView
當裝載活動在畫面上放置片段時,將會由主控活動呼叫,並傳回 View
。 一般 OnCreateView
會藉由擴充版面配置檔案,然後將它附加至父容器來建立此 View
專案。 容器的特性很重要,因為 Android 會將父系的配置參數套用至片段的 UI。 下列範例會加以說明:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.Inflate(Resource.Layout.Example_Fragment, container, false);
}
上述程式碼會擴大檢視 Resource.Layout.Example_Fragment
,並將其新增為容器的 ViewGroup
子檢視。
注意
片段子類別必須具有公用預設無引數建構函式。
將片段新增至活動
片段可以裝載于活動內的方式有兩種:
以宣告方式 – 片段可以在版面配置檔案中使用
.axml
宣告方式,方法是使用<Fragment>
標籤。以程式設計方式 – 片段也可以使用 類別的 API 動態
FragmentManager
具現化。
本指南稍後將討論透過 FragmentManager
類別的程式設計使用方式。
以宣告方式使用片段
在版面配置內新增片段需要使用 <fragment>
標籤,然後藉由提供 class
屬性或 android:name
屬性來識別片段。 下列程式碼片段示範如何使用 class
屬性來宣告 fragment
:
<?xml version="1.0" encoding="utf-8"?>
<fragment class="com.xamarin.sample.fragments.TitlesFragment"
android:id="@+id/titles_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
下一個程式碼片段示範如何使用 屬性來宣告 fragment
android:name
,以識別 Fragment 類別:
<?xml version="1.0" encoding="utf-8"?>
<fragment android:name="com.xamarin.sample.fragments.TitlesFragment"
android:id="@+id/titles_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
建立活動時,Android 會具現化配置檔案中指定的每個片段,並插入從 OnCreateView
建立的檢視來取代 Fragment
元素。
以宣告方式新增至活動的片段是靜態的,且會保留在活動上,直到終結為止;在附加活動的活動存留期間,無法動態取代或移除這類片段。
每個片段都必須指派唯一識別碼:
android:id – 如同版面配置檔案中的其他 UI 元素,這是唯一的識別碼。
android:tag – 此屬性是唯一的字串。
如果上述兩種方法都未使用,則 Fragment 會假設容器檢視的識別碼。 在下列範例中, android:id
其中未提供 或 android:tag
,Android 會將識別碼 fragment_container
指派給 Fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="+@id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.example.android.apis.app.TitlesFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
套件名稱大小寫
Android 不允許套件名稱中的大寫字元;如果封裝名稱包含大寫字元,則嘗試擴充檢視時,它會擲回例外狀況。 不過,Xamarin.Android 更適合使用,而且會容許命名空間中的大寫字元。
例如,下列兩個程式碼片段都會使用 Xamarin.Android。 不過,第二個程式碼片段會導致 android.view.InflateException
純 JAVA 型 Android 應用程式擲回 。
<fragment class="com.example.DetailsFragment" android:id="@+id/fragment_content" android:layout_width="match_parent" android:layout_height="match_parent" />
OR
<fragment class="Com.Example.DetailsFragment" android:id="@+id/fragment_content" android:layout_width="match_parent" android:layout_height="match_parent" />
片段生命週期
片段有自己的生命週期,與 裝載活動的生命週期稍有獨立,但仍受到影響。 例如,當活動暫停時,其所有相關聯的片段都會暫停。 下圖概述片段的生命週期。
片段建立生命週期方法
下列清單顯示片段生命週期中各種回呼的流程,因為其正在建立:
OnInflate()
– 在檢視配置中建立片段時呼叫。 這可以在從 XML 版面配置檔案宣告建立片段之後立即呼叫。 片段尚未與其活動相關聯,但檢視階層中的 Activity、 Bundle和 AttributeSet 會以參數的形式傳入。 此方法最適合用於剖析 AttributeSet ,以及儲存片段稍後可能使用的屬性。OnAttach()
– 在片段與活動相關聯之後呼叫。 這是當片段準備好使用時要執行的第一個方法。 一般而言,片段不應該實作建構函式或覆寫預設建構函式。 片段所需的任何元件都應該在此方法中初始化。OnCreate()
– 由活動呼叫以建立片段。 呼叫這個方法時,主控活動的檢視階層可能不會完全具現化,因此片段不應該依賴活動檢視階層的任何部分,直到稍後在片段生命週期中為止。 例如,請勿使用這個方法來對應用程式的 UI 執行任何調整或調整。 這是片段開始收集資料所需的最早時間。 片段目前在 UI 執行緒中執行,因此請避免任何冗長的處理,或在背景執行緒上執行該處理。 如果呼叫 SetRetainInstance (true) ,可能會略過這個方法。 以下將詳細說明此替代專案。OnCreateView()
– 建立片段的檢視。 一旦 Activity 的 OnCreate () 方法完成,就會呼叫這個方法。 此時,與活動的檢視階層互動是安全的。 這個方法應該會傳回 Fragment 將使用的檢視。OnActivityCreated()
– 在裝載活動完成 Activity.OnCreate 之後呼叫。 此時應該對使用者介面進行最終調整。OnStart()
– 在包含的活動繼續之後呼叫。 這可讓使用者看見片段。 在許多情況下,Fragment 會包含程式碼,否則會位於 Activity 的 OnStart () 方法中。OnResume()
– 這是使用者與片段互動之前所呼叫的最後一個方法。 在此方法中應該執行的程式碼類型範例,就是啟用使用者可能會與之互動的裝置功能,例如位置服務的相機。 不過,這類服務可能會導致電池耗盡過多,而應用程式應該盡可能減少其使用來保留電池使用時間。
片段解構生命週期方法
下一個清單說明即將終結當做片段呼叫的生命週期方法:
OnPause()
– 使用者無法再與片段互動。 這種情況存在,因為某些其他片段作業正在修改此片段,或裝載活動已暫停。 裝載此片段的活動可能仍然可見,也就是說,焦點中的活動是部分透明或未佔用全螢幕。 當這個方法變成作用中時,這是使用者離開片段的第一個指示。 片段應該儲存任何變更。OnStop()
– 片段已不再顯示。 主機活動可能會停止,或片段作業正在活動中修改。 此回呼的用途與 Activity.OnStop相同。OnDestroyView()
– 呼叫這個方法來清除與檢視相關聯的資源。 當與片段相關聯的檢視已終結時,就會呼叫這個值。OnDestroy()
– 當片段不再使用時,就會呼叫這個方法。 它仍然與活動相關聯,但片段已不再運作。 此方法應該釋放 Fragment 使用的任何資源,例如可能用於相機的 SurfaceView 。 如果呼叫 SetRetainInstance (true) ,可能會略過這個方法。 以下將詳細說明此替代專案。OnDetach()
– 這個方法會在片段不再與活動相關聯之前呼叫。 片段的檢視階層已不存在,而且片段所使用的所有資源此時都應該釋出。
使用 SetRetainInstance
如果重新建立活動,片段就可能指定不應該完全終結。 類別 Fragment
提供這個用途的 方法 SetRetainInstance
。 如果 true
傳遞至此方法,則當活動重新開機時,將會使用相同的 Fragment 實例。 如果發生這種情況,則會叫用所有回呼方法,但 和 OnDestroy
生命週期回呼除外 OnCreate
。 此程式顯示在上方的生命週期圖表中,由綠色虛線) 顯示 (。
片段狀態管理
片段可以使用 的 Bundle
實例,在片段生命週期中儲存和還原其狀態。 套件組合可讓片段將資料儲存為索引鍵/值組,對於不需要太多記憶體的簡單資料很有用。 片段可以儲存其狀態,並呼叫 OnSaveInstanceState
:
public override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
outState.PutInt("current_choice", _currentCheckPosition);
}
建立片段的新實例時,儲存在 中的 Bundle
狀態將會透過 OnCreate
新實例的 、 OnCreateView
和 OnActivityCreated
方法,提供給新實例使用。
下列範例示範如何從 Bundle
擷取 值 current_choice
:
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
if (savedInstanceState != null)
{
_currentCheckPosition = savedInstanceState.GetInt("current_choice", 0);
}
}
覆寫 OnSaveInstanceState
是一種適當的機制,可在片段中跨方向變更儲存暫時性資料,例如 current_choice
上述範例中的值。 不過,的預設實 OnSaveInstanceState
作會負責針對已指派識別碼的每個檢視,在 UI 中儲存暫時性資料。 例如,查看在 EditText
XML 中定義元素的應用程式,如下所示:
<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
EditText
由於控制項已 id
指派,因此呼叫 時,Fragment 會自動將資料儲存在小工具 OnSaveInstanceState
中。
套件組合限制
雖然 使用 OnSaveInstanceState
可讓您輕鬆地儲存暫時性資料,但使用此方法有一些限制:
如果未將片段新增至返回堆疊,當使用者按下 [ 上一步 ] 按鈕時,將不會還原其狀態。
當套件組合用來儲存資料時,就會序列化該資料。 這可能會導致處理延遲。
參與功能表
片段可能會將專案提供給其主控活動的功能表。 活動會先處理功能表項目。 如果活動沒有處理常式,則會將事件傳遞至 Fragment,然後處理該事件。
若要將專案新增至活動的功能表,片段必須執行兩件事。
首先,Fragment 必須實作 方法 OnCreateOptionsMenu
,並將其專案放在功能表中,如下列程式碼所示:
public override void OnCreateOptionsMenu(IMenu menu, MenuInflater menuInflater)
{
menuInflater.Inflate(Resource.Menu.menu_fragment_vehicle_list, menu);
base.OnCreateOptionsMenu(menu, menuInflater);
}
上一個程式碼片段中的功能表會從下列 XML 擴充,位於 檔案 menu_fragment_vehicle_list.xml
中:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/add_vehicle"
android:icon="@drawable/ic_menu_add_data"
android:title="@string/add_vehicle" />
</menu>
接下來,Fragment 必須呼叫 SetHasOptionsMenu(true)
。 此方法的呼叫會向 Android 宣告 Fragment 有功能表項目可參與選項功能表。 除非呼叫此方法,否則不會將 Fragment 的功能表項目新增至活動的選項功能表。 這通常是在生命週期方法 OnCreate()
中完成,如下一個程式碼片段所示:
public override void OnCreate(Bundle savedState)
{
base.OnCreate(savedState);
SetHasOptionsMenu(true);
}
下列畫面顯示此功能表的外觀: