我們都知道,Android上的界面展示都是通過Activity實現的,Activity實在是太常用了,我相信大家都已經非常熟悉了,這裡就不再贅述。
但是Activity也有它的局限性,同樣的界面在手機上顯示可能很好看,在平板上就未必了,因為平板的屏幕非常大,手機的界面放在平板上可能會有過分被拉長、控件間距過大等情況。這個時候更好的體驗效果是在Activity中嵌入小Activity,然後每個小Activity又可以擁有自己的布局。因此,我們今天的主角Fragment登場了。
Fragment初探
為了讓界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常類似於Activity,可以像Activity一樣包含布局。Fragment通常是嵌套在Activity中使用的,現在想象這種場景:有兩個Fragment,Fragment 1包含了一個ListView,每行顯示一本書的標題。Fragment 2包含了TextView和ImageView,來顯示書的詳細內容和圖片。
由此可以看出,使用Fragment可以讓我們更加充分地利用平板的屏幕空間,下面我們一起來探究下如何使用Fragment。
首先需要注意,Fragment是在3.0版本引入的,如果你使用的是3.0之前的系統,需要先導入android-support-v4的jar包才能使用Fragment功能。
新建一個項目叫做Fragments,然後在layout文件夾下新建一個名為fragment1.xml的布局文件:
[html]
- android:layout_width=match_parent
- android:layout_height=match_parent
- android:background=#00ff00 >
-
- android:layout_width=wrap_content
- android:layout_height=wrap_content
- android:text=This is fragment 1
- android:textColor=#000000
- android:textSize=25sp />
-
-
可以看到,這個布局文件非常簡單,只有一個LinearLayout,裡面加入了一個TextView。我們如法炮制再新建一個fragment2.xml :
[html]
- android:layout_width=match_parent
- android:layout_height=match_parent
- android:background=#ffff00 >
-
- android:layout_width=wrap_content
- android:layout_height=wrap_content
- android:text=This is fragment 2
- android:textColor=#000000
- android:textSize=25sp />
-
-
然後新建一個類Fragment1,這個類是繼承自Fragment的: [java] view plaincopy
- public class Fragment1 extends Fragment {
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment1, container, false);
- }
-
- } 我們可以看到,這個類也非常簡單,主要就是加載了我們剛剛寫好的fragment1.xml布局文件並返回。同樣的方法,我們再寫好Fragment2 : [java]
- public class Fragment2 extends Fragment {
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment2, container, false);
- }
-
- } 然後打開或新建activity_main.xml作為主Activity的布局文件,在裡面加入兩個Fragment的引用,使用android:name前綴來引用具體的Fragment: [html] view plaincopy
- android:layout_width=match_parent
- android:layout_height=match_parent
- android:baselineAligned=false >
-
- android:id=@+id/fragment1
- android:name=com.example.fragmentdemo.Fragment1
- android:layout_width=0dip
- android:layout_height=match_parent
- android:layout_weight=1 />
-
- android:id=@+id/fragment2
- android:name=com.example.fragmentdemo.Fragment2
- android:layout_width=0dip
- android:layout_height=match_parent
- android:layout_weight=1 />
-
- 最後打開或新建MainActivity作為程序的主Activity,裡面的代碼非常簡單,都是自動生成的: [java] view plaincopy
- public class MainActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
-
- }
現在我們來運行一次程序,就會看到,一個Activity很融洽地包含了兩個Fragment,這兩個Fragment平分了整個屏幕,
動態添加Fragment
你已經學會了如何在XML中使用Fragment,但是這僅僅是Fragment最簡單的功能而已。Fragment真正的強大之處在於可以動態地添加到Activity當中,因此這也是你必須要掌握的東西。當你學會了在程序運行時向Activity添加Fragment,程序的界面就可以定制的更加多樣化。下面我們立刻來看看,如何動態添加Fragment。
還是在上一節代碼的基礎上修改,打開activity_main.xml,將其中對Fragment的引用都刪除,只保留最外層的LinearLayout,並給它添加一個id,因為我們要動態添加Fragment,不用在XML裡添加了,刪除後代碼如下:
[html]
- android:id=@+id/main_layout
- android:layout_width=match_parent
- android:layout_height=match_parent
- android:baselineAligned=false >
-
- 然後打開MainActivity,修改其中的代碼如下所示: [java] view plaincopy
- public class MainActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Display display = getWindowManager().getDefaultDisplay();
- if (display.getWidth() > display.getHeight()) {
- Fragment1 fragment1 = new Fragment1();
- getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit();
- } else {
- Fragment2 fragment2 = new Fragment2();
- getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit();
- }
- }
-
- }
首先,我們要獲取屏幕的寬度和高度,然後進行判斷,如果屏幕寬度大於高度就添加fragment1,如果高度大於寬度就添加fragment2。動態添加Fragment主要分為4步:
1.獲取到FragmentManager,在Activity中可以直接通過getFragmentManager得到。
2.開啟一個事務,通過調用beginTransaction方法開啟。
3.向容器內加入Fragment,一般使用replace方法實現,需要傳入容器的id和Fragment的實例。
4.提交事務,調用commit方法提交。
Fragment的生命周期
和Activity一樣,Fragment也有自己的生命周期,理解Fragment的生命周期非常重要,我們通過代碼的方式來瞧一瞧Fragment的生命周期是什麼樣的:
[java]
- public class Fragment1 extends Fragment {
- public static final String TAG = Fragment1;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Log.d(TAG, onCreateView);
- return inflater.inflate(R.layout.fragment1, container, false);
- }
-
- @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 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);
- }
-
- } 可以看到,上面的代碼在每個生命周期的方法裡都打印了日志,然後我們來運行一下程序,可以看到打印日志如下:
看到這裡,我相信大多數朋友已經非常明白了,因為這和Activity的生命周期太相似了。只是有幾個Activity中沒有的新方法,這裡需要重點介紹一下: