探究碎片Fragment(2)
碎片的活動週期
活動中有的回撥方法,碎片 中幾乎都有,不過碎片還提供了一些附加的回撥方法,那我們就重點來看下這幾個回撥
- onAttach() 當碎片和活動建立關聯的時候呼叫
- onCreateView() 為碎片建立檢視(載入佈局)時呼叫
- onActivityCreated() 確保與碎片相關聯的活動一定已經建立完畢的時候呼叫
- onDestroyView() 當與碎片關聯的檢視被移除的時候呼叫
- onDetach() 當碎片和活動解除關聯的時候呼叫
在上一節的RightFragment的基礎上修改
public class RightFragment extends Fragment { public static final String TAG = "RightFragment"; @Override public void onAttach(Activity activity) { super.onAttach(activity); Log.d(TAG, "onAttach"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView"); View view = inflater.inflate(R.layout.right_fragment, container, false); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d(TAG, "onActivityCreated"); } @Override public void onStart() { super.onStart(); Log.d(TAG, "onStart"); } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume"); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause"); } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop"); } @Override public void onDestroyView() { super.onDestroyView(); Log.d(TAG, "onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } @Override public void onDetach() { super.onDetach(); Log.d(TAG, "onDetach"); } }
重新執行 程式,這時觀察 LogCat中的列印資訊
然後點選 LeftFragment中的按鈕,此時列印資訊
由於 AnotherRightFragment替換了 RightFragment,此時的 RightFragment進入了停止狀 態,因此 onPause()、onStop()和 onDestroyView()方法會得到執行。當然如果在替換的時候沒 有呼叫 addToBackStack()方法,此時的 RightFragment 就會進入銷燬狀態,onDestroy()和 onDetach()方法就會得到執行
接著按下 Back鍵,RightFragment會重新回到螢幕
由於 RightFragment 重新回到了執行狀態,因此 onActivityCreated()、onStart()和 onResume()方法會得到執行。注意此時 onCreate()和 onCreateView()方法並不會執行,因為我 們藉助了 addToBackStack()方法使得 RightFragment和它的檢視並沒有銷燬
再次按下 Back鍵退出程式
依次會執行 onPause()、onStop()、onDestroyView()、onDestroy()和 onDetach()方法,最 終將活動和碎片一起銷燬
動態載入佈局的技巧
如果你經常使用平板電腦,應該會發現很多的平板應用現在都採用的是雙頁模式(程式 會在左側的面板上顯示一個包含子項的列表,在右側的面板上顯示內容),因為平板電腦的 螢幕足夠大,完全可以同時顯示下兩頁的內容,但手機的螢幕一次就只能顯示一頁的內容,因此兩個頁面需要分開顯示
那麼怎樣才能在執行時判斷程式應該是使用雙頁模式還是單頁模式呢?這就需要藉助 限定符(Qualifiers)來實現了。我們通過一個例子來學習一下它的用法,修改 剛才專案中的 activity_main.xml檔案
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.xx.myapplication.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
這裡將多餘的程式碼都刪掉,只留下一個左側碎片,並讓它充滿整個父佈局
接著在 res 目錄下新建 layout-large資料夾,在這個資料夾下新建一個佈局,也叫做 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.xx.myapplication.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/right_fragment"
android:name="com.example.xx.myapplication.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
layout/activity_main 佈局只包含了一個碎片,即單頁模式,而 layout-large/ activity_main佈局包含了兩個碎片,即雙頁模式
其中 large就是一個限定符,那些螢幕被認 為是 large的裝置就會自動載入 layout-large資料夾下的佈局,而小螢幕的裝置則還是會載入 layout資料夾下的佈局
這樣我們就實現了在程式執行時動態載入佈局的功能。
Android中一些常見的限定符可以參考下表
使用最小寬度限定符
在上一小節中我們使用 large限定符成功解決了單頁雙頁的判斷問題,不過很快又有一 個新的問題出現了,large到底是指多大呢?有的時候我們希望可以更加靈活地為不同裝置加 載佈局,不管它們是不是被系統認定為“large”,這時就可以使用最小寬度限定符 (Smallest-widthQualifier)了
最小寬度限定符允許我們對螢幕的寬度指定一個最小指(以 dp為單位) ,然後以這個最 小值為臨界點,螢幕寬度大於這個值的裝置就載入一個佈局,螢幕寬度小於這個值的裝置就 載入另一個佈局
在 res 目錄下新建 layout-sw600dp 資料夾,然後在這個資料夾下新建 activity_main.xml 佈局,這就意味著,當程式執行在螢幕寬度大於 600dp 的裝置上時,會載入 layout-sw600dp/ activity_main 佈局,當程式執行在螢幕寬度小於 600dp 的裝置上時,則仍然載入預設的 layout/activity_main佈局