android之Fragment基礎詳解(一)


 

 

一、Fragment的設計哲學

  Android在3.0中引入了fragments的概念,主要目的是用在大屏幕設備上——例如平板電腦上,支持更加動態和靈活的UI設計。平板電腦的屏幕比手機的大得多,有更多的空間來放更多的UI組件,並且這些組件之間會產生更多的交互。

  針對屏幕尺寸的差距,很多情況下,都是先針對手機開發一套App,然后拷貝一份,修改布局以適應平板神馬超級大屏的。難道無法做到一個App可以同時適應手機和平板么,當然了,必須有啊。Fragment的出現就是為了解決這樣的問題。你可以把Fragment當成Activity的一個界面的一個組成部分,甚至Activity的界面可以完全有不同的Fragment組成,更帥氣的是Fragment擁有自己的生命周期和接收、處理用戶的事件,這樣就不必在Activity寫一堆控件的事件處理的代碼了。更為重要的是,你可以動態的添加、替換和移除某個Fragment。

  

下圖是文檔中給出的一個Fragment分別對應手機與平板間不同情況的處理圖:

5.1 Fragment基本概述0

5.1 Fragment基本概述0

PS:簡單的新聞瀏覽頁面,使用兩個Fragment分別顯示新聞列表與新聞內容;

  Fragment在應用中應當是一個模塊化和可重用的組件,因為Fragment定義了他自己的布局,以及通過使用他自己的生命周期回調方法定義了他自己的行為,可以將Fragment包含到多個Activity中。

二、靜態加載Fragment

  Fragment知識概要:

    • Fragment 可以作為Activity界面的一部分組成出現(不能單獨使用)
    • 可以在一個Activity中同時出現多個fragment,並且一個fragment也可以在多個activity中使用
    • 在activity運行過程中,可以添加、一處或替換fragment
    • fragment可以響應自己的輸入事件,並且有自己的生命周期,他們的生命周期會受宿主activity的生命周期影響,比如Activity被destory銷毀了,他也會跟着銷毀

  

 

onCreateView()方法

  Fragment第一次繪制它的用戶界面的時候,系統會調用此方法,未來繪制Fragment的UI,此方法必須返回一個View,如果不顯示UI,返回NULL即可。

 

  在activity的layout文件中聲明Fragment,需要特別注意的是<fragment>中的android: name 屬性指定了在layout中實例化的Fragment類

  標識Fragment的方法:

    android:id 屬性提供一個唯一的ID

    android:tag 屬性提供一個唯一字符串

1、fragment布局文件,顯示fragment顯示內容控件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     
 7     <TextView
 8        android:id="@+id/text"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         ></TextView>
12     
13     <Button 
14         android:id="@+id/button"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         
18         />
19 </LinearLayout>
fragment.xml

2、自定義一個Fragment類,需要繼承Fragment或者他的子類,重寫onCreateView()方法 在該方法中調用:inflater.inflate()方法加載Fragment的布局文件,接着返回加載的view對象

 1 package com.example.fragment;
 2 
 3 import android.app.Fragment;
 4 import android.os.Bundle;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.TextView;
 9 
10 public class MyFragment extends Fragment{
11     @Override
12     public View onCreateView(LayoutInflater inflater, ViewGroup container,
13             Bundle savedInstanceState) {
14         
15         //layout布局文件轉換成view對象
16         /**
17          * resource:Fragment需要加載的布局文件
18          * root:加載layout的父ViewGroup
19          * attachToRoot:flase,不反回父ViewGroup
20          */
21         View view = inflater.inflate(R.layout.fragment, container, false);
22         TextView text = (TextView) view.findViewById(R.id.text);
23         text.setText("加載靜態Fragment");
24         return view ;
25         
26     }
27 }
MyFragment.java

3、在需要加載Fragment的Activity對應的布局文件中添加fragment的標簽, 記住,name屬性是全限定類名哦,就是要包含Fragment的包名

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     
 7     <fragment 
 8         android:id="@+id/fragment" 
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11           android:name="com.example.fragment.MyFragment"
12         />
13 </LinearLayout>
main2.xml

4、 Activity在onCreate( )方法中調用setContentView()加載布局文件即可!(可添加事件)

 1 import android.view.View.OnClickListener;
 2 import android.widget.Button;
 3 import android.widget.TextView;
 4 
 5 public class MainActivity2 extends Activity{
 6     
 7     private TextView tv;
 8     
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         
12         setContentView(R.layout.main2);
13         
14         Button button = (Button) findViewById(R.id.button);
15         tv = (TextView) findViewById(R.id.text);
16         button.setText("改變");
17         button.setOnClickListener(new OnClickListener() {
18             
19             @Override
20             public void onClick(View v) {
21                 tv.setText("TextView改變了");
22             }
23         });
24     }
25 }
MainActivity2.java

 

 

三、動態加載

  撰寫代碼將Fragmen添加到一個Activity layout 中

    add():添加一個Fragment(指定要添加的fragment 和 要插入的View)

    與此類似的還有remove() 、替換()

  處理Frament事務

  格局用戶的交互情況,對Fragment進行添加、移除、替換,以及執行其他動作,提交給Activity的每一套變化被稱作一個事務

  FragmentManager fragmentManager = getFragmentManager();

  FragmentTransaction beginTransaction = fragmentManager.beginTransaction();

  每一個事務都是同時執行一套變化,可以在一個事務中設置所有想執行的變化,包括add()、remove()、replace()、然后提交給Activity,必須調用commit()方法

  如果允許用戶通過按下back按鍵返回到前一個Fragment狀態,調用commit()之前可以加入addToBackStack()方法

 

 MyFragment2.xml

 1 package com.example.fragment;
 2 
 3 import android.app.Fragment;
 4 import android.os.Bundle;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.TextView;
 9 
10 public class MyFragment2 extends Fragment{
11     @Override
12     public View onCreateView(LayoutInflater inflater, ViewGroup container,
13             Bundle savedInstanceState) {
14         
15         //layout布局文件轉換成view對象
16         /**
17          * resource:Fragment需要加載的布局文件
18          * root:加載layout的父ViewGroup
19          * attachToRoot:flase,不反回父ViewGroup
20          */
21         View view = inflater.inflate(R.layout.fragment, container, false);
22         TextView text = (TextView) view.findViewById(R.id.text);
23         text.setText("動態加載Fragment");
24         return view ;
25         
26     }
27 }
MyFragment2

主要代碼

 

Fragment與activity通信

生命周期圖:

  

 

探究fragment生命周期案例:

  

 1 package com.example.fragment;
 2 
 3 import android.app.Activity;
 4 import android.app.FragmentManager;
 5 import android.app.FragmentTransaction;
 6 import android.os.Bundle;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.widget.Button;
10 
11 public class MainActivity3 extends Activity {
12 
13     private Button button;
14     private boolean flag = true;
15     
16     
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.main3);
21         init();
22         button = (Button) findViewById(R.id.button);
23         button.setOnClickListener(new OnClickListener() {
24 
25             @Override
26             public void onClick(View v) {
27                 FragmentManager fragmentManager = getFragmentManager();
28                 FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
29                 
30                 if (flag) {
31                     MyFragment4 frag4=new MyFragment4();
32                     beginTransaction.replace(R.id.layout, frag4);
33                     flag=false;
34                 } else {
35                     MyFragment3 frag3=new MyFragment3();
36                     beginTransaction.replace(R.id.layout, frag3);
37                     flag=true;
38 
39                 }
40                 
41                beginTransaction.commit();
42             }
43         });
44 
45     }
46 
47     private void init() {
48         FragmentManager fragmentManager = getFragmentManager();
49         FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
50         MyFragment3 frag3 = new MyFragment3();
51         beginTransaction.add(R.id.layout,frag3);
52         beginTransaction.commit();
53     }
54 
55 }
MainActivity3.java
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:id="@+id/layout"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:orientation="vertical" >
 7 
 8     <Button
 9         android:text="切換Fragment"
10         android:id="@+id/button"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content" >
13     </Button>
14 
15 </LinearLayout>
main3.xml
  1 package com.example.fragment;
  2 
  3 import android.app.Activity;
  4 import android.app.Fragment;
  5 import android.os.Bundle;
  6 import android.util.Log;
  7 import android.view.LayoutInflater;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10 import android.widget.TextView;
 11 
 12 public class MyFragment3 extends Fragment {
 13 
 14     /**
 15      * 每次創建都會繪制Fragment的View組件
 16      */
 17     @Override
 18     public View onCreateView(LayoutInflater inflater, ViewGroup container,
 19             Bundle savedInstanceState) {
 20         View view = inflater.inflate(R.layout.fragment2, container, false);
 21         TextView tv = (TextView) view.findViewById(R.id.text);
 22         tv.setText("第一個ragment");
 23         Log.i("Main", "Fragment1---onCreateView()");
 24         return view;
 25     }
 26 
 27     /**
 28      * 當fragment被添加Activity時候慧回調此方法,並且只調用一次
 29      */
 30     @Override
 31     public void onAttach(Activity activity) {
 32         super.onAttach(activity);
 33         Log.i("Main", "Fragment1---onAttach()");
 34 
 35     }
 36 
 37     /**
 38      * 創建Fragment時回調
 39      */
 40     @Override
 41     public void onCreate(Bundle savedInstanceState) {
 42         super.onCreate(savedInstanceState);
 43         Log.i("Main", "Fragment1---onCreate()");
 44 
 45     }
 46 
 47     /**
 48      * 當Fragment所長的activity啟動完成后調用
 49      */
 50     @Override
 51     public void onActivityCreated(Bundle savedInstanceState) {
 52             super.onActivityCreated(savedInstanceState);
 53         Log.i("Main", "Fragment1---onActivityCreated()");
 54 
 55     }
 56 
 57     /**
 58      * 啟動Fragment
 59      * 
 60      */
 61     @Override
 62     public void onStart() {
 63         super.onStart();
 64         Log.i("Main", "Fragment1---onStart()");
 65 
 66     }
 67 
 68     /**
 69      * 恢復Fragment時會被回調,調用onStart()方法后 一定調用onResume()方法
 70      */
 71     @Override
 72     public void onResume() {
 73         super.onResume();
 74         Log.i("Main", "Fragment1---onResume()");
 75 
 76     }
 77 
 78     /**
 79      * 暫停Fragment
 80      */
 81     @Override
 82     public void onPause() {
 83         super.onPause();
 84         Log.i("Main", "Fragment1---onPause()");
 85 
 86     }
 87 
 88     /**
 89      * 停止Fragment
 90      */
 91     @Override
 92     public void onStop() {
 93         super.onStop();
 94         Log.i("Main", "Fragment1---onStop()");
 95 
 96     }
 97 
 98     /**
 99      *銷毀 Fragment所包含的View組件
100      */
101     @Override
102     public void onDestroyView() {
103         super.onDestroyView();
104         Log.i("Main", "Fragment1---onDestroyView()");
105 
106     }
107 
108     /**
109      * 銷毀Fragment是被回調
110      */
111     @Override
112     public void onDestroy() {
113         super.onDestroy();
114         Log.i("Main", "Fragment1---onDestroy()");
115 
116     }
117 
118     /**
119      * Fragment從Activity中刪除時會回調該方法,只會調用一次
120      */
121     @Override
122     public void onDetach() {
123         super.onDetach();
124         Log.i("Main", "Fragment1---onDetach()");
125     }
126 }
MyFragment3.java
MyFragment4.java

  

測試順序:啟動fragment—>回到桌面—>回到應用—>切換fragment—>退出fragment

日志打印:

     

    

  總結:

  1)啟動fragment

  onAttach()—>onCreat()—>onCreateView()—>onActivityCreated()—>onStart()—>onResume()

  2)鎖屏

  onPause()—>onStop()

  3)解鎖

  onStart()—>onResume()

  4)切換到其他的Fragment

  第一個:onPause()—>onStop()—>onDestroyView()—>onDestroy()—>onDetach

  第二個:onAttach()—>onCreat()—>onCreateView()—>onActivityCreated()—>onStart()—>onResume()

 

Fragment 與Activity通信

  1)Fragment可調用getActivity()方法獲取它所在的Activity

  2)Activity可調用FragmentManager的findFragmentById()或findFragmentByTag()方法獲取Fragment

 

Activity——>Fragment:在Activity中創建Bundle數據包,並調用Fragment的setArguments(Bundle bundle)方法

 

Fragment——>Activity:需要在Fragment中定義一個內部回調接口,再讓包含該Fragment的Activity實現該回調接口。這樣Fragment可調用該回調方法將數據傳遞給Activity

 

 

更詳細也可以參考:http://www.itnose.net/detail/6396730.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM