建立片段
若要建立 Fragment,類別必須繼承自 Android.App.Fragment
,然後覆寫 OnCreateView
方法。 OnCreateView
當載入活動將片段放在畫面上時,會由主控活動呼叫,並會傳回 View
。 一般 OnCreateView
會藉由擴充版面配置檔案,然後將它附加至父容器來建立此 View
檔案。 容器的特性很重要,因為Android會將父系的配置參數套用至 Fragment 的 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
屬性來識別 Fragment。 下列代碼段示範如何使用 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
指派給片段:
<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()
– 在片段與活動相關聯之後呼叫。 這是當 Fragment 準備好使用時要執行的第一個方法。 一般而言,片段不應該實作建構函式或覆寫預設建構函式。 片段所需的任何元件都應該在此方法中初始化。OnCreate()
– 由活動呼叫以建立片段。 呼叫這個方法時,主控活動的檢視階層可能不會完全具現化,因此在片段生命週期稍後之前,片段不應依賴活動檢視階層的任何部分。 例如,請勿使用此方法對應用程式的UI執行任何調整或調整。 這是片段最早可能開始收集數據的時間。 片段目前在UI線程中執行,因此請避免任何冗長的處理,或在背景線程上執行該處理。 如果 呼叫 SetRetainInstance(true), 可能會略過這個方法。 以下將詳細說明此替代方案。OnCreateView()
– 建立片段的檢視。 一旦 Activity 的 OnCreate() 方法完成,就會呼叫這個方法。 此時,與活動的檢視階層互動是安全的。 這個方法應該會傳回 Fragment 將使用的檢視。OnActivityCreated()
– 在裝載活動完成 Activity.OnCreate 之後呼叫。 此時應該執行使用者介面的最終調整。OnStart()
– 在包含的活動恢復之後呼叫。 這可讓使用者看到片段。 在許多情況下,Fragment 會包含程式代碼,否則會位於 Activity 的 OnStart() 方法中。OnResume()
– 這是使用者與 Fragment 互動之前所呼叫的最後一個方法。 這個方法中應該執行的程式代碼類型範例,就是啟用使用者可能與之互動的裝置功能,例如定位服務的相機。 不過,這類服務可能會導致過多的電池耗盡,而應用程式應儘可能減少其用來保留電池使用時間。
片段解構生命週期方法
下一個清單說明正在終結作為片段呼叫的生命週期方法:
OnPause()
– 用戶無法再與片段互動。 這種情況存在,因為其他片段作業正在修改此片段,或主控活動已暫停。 裝載此片段的活動可能仍然可見,也就是說,焦點中的活動部分透明或未佔用全螢幕。 當此方法變成作用中時,這是用戶離開 Fragment 的第一個指示。 片段應該儲存任何變更。OnStop()
– 片段已不再顯示。 主機活動可能會停止,或片段作業正在活動中修改它。 此回呼的作用與 Activity.OnStop 相同。OnDestroyView()
– 呼叫這個方法以清除與檢視相關聯的資源。 當與片段相關聯的檢視已終結時,就會呼叫這個值。OnDestroy()
– 當片段不再使用時,會呼叫這個方法。 它仍然與活動相關聯,但片段已不再運作。 這個方法應該釋放 Fragment 使用的任何資源,例如 可能用於相機的 SurfaceView 。 如果 呼叫 SetRetainInstance(true), 可能會略過這個方法。 以下將詳細說明此替代方案。OnDetach()
– 這個方法會在片段不再與活動相關聯之前呼叫。 片段的檢視階層已不存在,且片段所使用的所有資源此時都應該釋出。
使用 SetRetainInstance
片段可以指定,如果重新建立活動,則不應該完全終結該片段。 類別 Fragment
會針對此目的提供方法 SetRetainInstance
。 如果 true
傳遞至這個方法,則當活動重新啟動時,將會使用相同的 Fragment 實例。 如果發生這種情況,則會叫用所有回呼方法,但和 OnDestroy
生命週期回呼除外OnCreate
。 此程序顯示在上圖的生命週期圖表中(由綠色虛線)。
片段狀態管理
片段可以使用 的 Bundle
實例,在片段生命週期期間儲存和還原其狀態。 套件組合可讓片段將數據儲存為索引鍵/值組,而且對於不需要太多記憶體的簡單數據很有用。 Fragment 可以儲存其狀態,並呼叫 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 中儲存暫時性數據。 例如,查看 XML EditText
中定義元素的應用程式,如下所示:
<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
EditText
由於控件已id
指派,因此當呼叫 時OnSaveInstanceState
,Fragment 會自動將數據儲存在小工具中。
套件組合限制
雖然 使用 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 有功能表項,以參與選項功能表。 除非呼叫此方法,否則不會將片段的功能表項新增至活動的選項功能表。 這通常是在生命週期方法 OnCreate()
中完成,如下一個代碼段所示:
public override void OnCreate(Bundle savedState)
{
base.OnCreate(savedState);
SetHasOptionsMenu(true);
}
下列畫面顯示此功能表的外觀: