1. 程式人生 > >Fragment的詳細介紹和使用方法及案例

Fragment的詳細介紹和使用方法及案例

由於TabActivity在Android4.0以後已經被完全棄用,那麼我就不再浪費口水繼續講解它了,取而代之的是Fragment。Fragment是Android3.0新增的概念,Fragment翻譯成中文是碎片的意思,不過卻和Activity十分的相似,這一篇我花大量的篇幅來詳細的講解Fragment的介紹和使用方法。


一、Fragment的基礎知識介紹

1.1概述

1.1.1 特性

        Fragment是activity的介面中的一部分或一種行為。可以把多個Fragment組合到一個activity中來建立一個多介面

並且可以在多個activity中重用一個Fragment。可以把Fragment任務模組化的一段activity,它具有自己的生命週期,

接收它自己的事件,並可以在activity執行時被新增或刪除。

       Fragment不能獨立存在,它必須嵌入到activity中,而且Fragment的生命週期直接受所在的activity的影響。例

如:當activity暫停時,他擁有的所有的Fragment都暫停了,當activity銷燬時,他擁有的所有Fragment都被銷燬。然

而,當activity執行時(在onResume()之後,onPause()之前),可以單獨地操作每個Fragment,比如新增或刪除它

們。當中執行上述針對Fragment的事務時,可以將事務新增到一個棧中,這個棧被activity管理,棧中的每一條都是一

個Fragment的一次事務。有了這個棧,就可以反向執行Fragment的事務,這樣就可以在Fragment級支援“返回”鍵

(向後導航)。

        當向activity中新增一個Fragment時,它須置於ViewGroup控制元件中,並且需定義Fragment自己的介面。可以在

layout.xml佈局檔案中宣告Fragment,元素為:<fragment>;也可以在程式碼中建立Fragment,然後把它加入到

ViewGroup控制元件中。然而,Fragment不一定非要放在activity的介面中,它可以隱藏在後臺為activity工作。


1.1.2 生命週期

onCreate():

     當建立fragment時系統呼叫此方法。在其中必須初始化fragment的基礎元件們。可參考activity的說明;

onCreateView():

     系統在fragment要畫自己的介面時呼叫(在真正顯示之前)此方法,這個方法必須返回fragment的layout的根控

件,如果這個fragment不提供介面,那它應返回null;

onPause():

     大多數程式應最少對fragment實現這三個方法,當然還有其它幾個回撥方法可應該按情況實現之,所有的宣告週期

回撥函式在“操控fragment的生命週期”一節中有詳細討論。

下圖為fragment的生命週期(它所在的activity處於執行狀態)


Activity和Fragment生命週期對比圖如下:

兩個的生命週期很類似,也息息相關。


1.1.3 派生類

DialogFragment

    顯示一個浮動的對話方塊。使用這個類建立對話方塊是替代activity建立對話方塊的最佳選擇。因為可以把fragmentdialog

放入到activity的返回棧中,使使用者能再返回到這個對話方塊。

ListFragment

    顯示一個列表控制元件,就像ListActivity類,它提供了很多管理列表的方法,比如onListItemClick()方法響應click事件。

PreferenceFragment

    顯示一個由Preference物件組成的列表,與PreferenceActivity相同。它用於為程式建立“設定”activity。

1.2 範例

     寫一個讀新聞的程式,可以用一個fragment顯示標題列表,另一個fragment顯示選中標題的內容,這兩個fragment

都在一個activity上,並排顯示。那麼這兩個fragment都有自己的生命週期並響應自己感興趣的事件。於是,不需要再

像手機上那樣用一個activity顯示標題列表,用另一個activity顯示新聞內容;現在可以把兩者放在一個activity上同時顯

示出來。如下圖:

       Fragment必須被寫成可重用的模組。因為fragment有自己的layout,自己進行事件響應,擁有自己的生命週期和

行為,所以可以在多個activity中包含同一個Fragment的不同例項。這對於讓世界在不同的螢幕尺寸下都能給使用者完美

的體驗尤其重要。比如可以在程式運行於大螢幕中時啟動包含很多fragment的activity,而在執行小螢幕時啟動一個包

含少量fragment的activity。

        剛才讀新聞的程式,當檢測到程式運行於大螢幕時,啟動activityA,將標題列表和新聞內容這兩個fragment都放

在activityA中;當檢測到程式運行於小螢幕時,還是啟動activityA,但此時A中只有標題列表fragment,當選中一個標

題時,activityA啟動activityB,B中含有新聞內容fragment。


1.3 建立Fragment

         要建立fragment,必須從Fragment或Fragment的派生類派生出一個類。Fragment的程式碼寫起來有些像activity。

它具有跟activity一樣的回撥方法,比如onCreate(),onStart(),onPause()和onStop()。實際上,如果想把老的程式改為

使用fragment,基本上只需要把activity的回撥方法的程式碼移到fragment中對應的方法即可。

1.3.1新增有介面的Fragment

       Fragment一般作為activity的使用者介面的一部分,把它自己layout嵌入到activity的layout中。一個要為fragment提

供layout,必須實現onCreateView()回撥方法,然後在這個方法中返回一個View物件,這個物件時fragment的layout的

根。

       注意:如果fragment是從ListFragment中派生的,就不需要實現onCreateView()方法了,因為預設的實現已經返

回了ListView控制元件物件。

       要從onCreateView()方法中返回layout物件,可以從layout.xml佈局檔案中生成layout物件。為了幫助這樣做,

onCreateView()提供了一個layoutInflater物件。舉例:以下程式碼展示了一個Fragment的子類如何從layout.xml佈局檔案

example_fragment.xml中生成物件。

  1. <span style="font-size:10px;">public static ExampleFragment extends Fragment {   
  2. @Override   
  3. publicView onCreateView(LayoutInflater inflater, ViewGroup container,   
  4. Bundle savedInstanceState) {   
  5. returninflater.inflate(R.layout.example_fragment, container, false);   
  6. }   
  7. }</span>  
複製程式碼 onCreateView()引數中的container是存放fragment的layout的ViewGroup物件。saveInstanceState引數是一個Bundle,跟activity的onCreate()中Bundle差不多,用於狀態恢復。但是fragment的onCreate()中也有Bundle引數,所以此處的Bundle中存放的資料與onCreate()中存放的資料還是不同的。Inflate()方法中有三個引數:  <1> layout的資源ID;  <2> 存放fragment的layout的ViewGroup;  <3> 布林資料表示是否在建立fragment的layout期間,把layout附加到container上(在這個例子中,因為系統已經把layout插入到container中了,所以值為false,如果為true會導致在最終的layout中建立多餘的ViewGroup)。      下面講述如何把它新增到activity中。把fragment新增到activity一般情況下,fragment把它的layout作為activity的layout的一部分合併到activity中,有兩種方法將一個fragment新增到activity中:
方法一:在activity的layout.xml檔案中宣告fragment
  1. <?xmlversionxmlversion="1.0" encoding="utf-8" ?>  
  2. <LinearLayoutxmlns:androidLinearLayoutxmlns:android=" http://schemas.android.com/apk/res/android"   
  3. android:orientation="horizontal"   
  4. android:layout_width="match_parent"   
  5. android:layout_height="match_parent" >  
  6. <fragmentandroid:namefragmentandroid:name="com.android.cwj.ArticleListFragment"   
  7. android:id="@+id/list"   
  8. android:layout_weight="1"   
  9. android:layout_width="0dp"   
  10. android:layout_height="match_parent" />  
  11. <fragmentandroid:namefragmentandroid:name="com.android.cwj.ArticleReaderFragment"   
  12. android:id="@+id/viewer"   
  13. android:layout_weight="2"   
  14. android:layout_width="0dp"   
  15. android:layout_height="match_parent" />  
  16. </LinearLayout>  
複製程式碼 以上程式碼中,<fragment>中宣告一個fragment。當系統建立上例中的layout時,它例項化每一個fragment,然後呼叫它們的onCreateView()方法,以獲取每個fragment的layout。系統把fragment返回的view物件插入到<fragment>元素的位置,直接代替<fragment>元素。注:每個fragment都需要提供一個ID,系統在activity重新建立時用它來恢復fragment,也可以用它來操作fragment進行其它的事物,比如刪除它。有三種方法給fragment提供ID:  <1> 為Android:id屬性賦一個數字;  <2> 為Android:tag屬性賦一個字串。如果沒有使用上述任何一種方法,系統將使用fragment的容器的ID。

方法二:在程式碼中新增fragment到一個ViewGroup        這種方法可以在執行時,把fragment新增到activity的layout中。只需指定一個要包含fragment的ViewGroup。為了完成fragment的事務(比如新增,刪除,替換等),必須使用FragmentTransaction的方法。可以從activity獲取FragmentTransaction,如下:
  1. FragmentManager fragmentManager = getFragmentManager();  
  2. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
複製程式碼 然後可以用add()方法新增一個fragment,它有引數用於指定容納fragment的ViewGroup。如,Add()的第一個引數是容器ViewGroup,第二個是要新增的fragment。一旦通過FragmentTransaction對fragment做出了改變,必須呼叫方法commit()提交這些改變。不僅在無介面的fragment中,在有介面的fragment中也可以使用tag來作為唯一的標誌,這樣在需要獲取fragment物件時,要呼叫findFragmentTag()。 1.3.2 新增沒有介面的Fragment         上面演示瞭如何新增fragment來提供介面,然而,也可以使用fragment為activity提供後臺的行為而不用顯示fragment的介面。要新增一個沒有介面的fragment,需要在activity中呼叫方法add(Fragment,String)(它支援用一個唯一的字串做為fragment的“tag”,而不是viewID)。這樣新增的fragment由於沒有介面,所以在實現它時不需要呼叫實現onCreateView()方法。        使用tag字串來標示一個fragment並不是只能用於沒有介面的fragment上,也可以把它用於有介面的fragment上,但是,如果一個fragment沒有介面,tag字串將成為它唯一的選擇。獲取以tag表示的fragment,需使用方法findFragmentByTab()。
1.4 Fragment管理      要管理fragment,需使用FragmentManager,要獲取它,需在activity中呼叫方法getFragmentManager()。可以用FragmentManager來做以下事情:      <1> 使用方法findFragmentById()或findFragmentByTag(),獲取activity中已存在的fragment;      <2> 使用方法popBackStack()從activity的後退棧中彈出fragment(這可以模擬後退鍵引發的動作),用方法addOnBackStackChangedListenner()註冊一個偵聽器以監視後退棧的變化;      <3> 還可以使用FragmentManager開啟一個FragmentTransaction來執行fragment的事務,比如新增或刪除fragment。       在activity中使用fragment的一個偉大的好處是能根據使用者的輸入對fragment進行新增、刪除、替換以及執行其他動作的能力。提交的一組fragment的變化叫做一個事務。事務通過FragmentTransaction來執行。還可以把每個事務儲存在activity的後退棧中,這樣就可以讓使用者在fragment變化之間導航(跟在activity之間導航一樣)。
可以通過FragmentManager來取得FragmentTransaction的例項,如下:
  1. FragmentManager fragmentManager = getFragmentManager();  
  2. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
複製程式碼 一個事務是在同一時刻執行的一組動作(很像資料庫中的事務)。可以用add(),remove(),replace()等方法構成事務,最後使用commit()方法提交事務。在呼叫commit()之前,可以用addToBackStack()把事務新增到一個後退棧中,這個後退棧屬於所在的activity。有了它,就可以在使用者按下返回鍵時,返回到fragment執行事務之前的狀態。如下例:演示瞭如何用一個fragment代替另一個fragment,同時在後退棧中儲存被代替的fragment的狀態。
  1. //建立一個fragment  
  2. Fragment newFragment = new ExampleFragment();  
  3. //例項化fragment事務管理器  
  4. FragmentTransaction transaction = getFragmentManager().beginTransaction();  
  5. //用新建立的fragment來代替fragment_container  
  6. transaction.replace(R.id.fragment_container,newFragment);  
  7. //新增進棧中  
  8. transaction.addToBackStack(null);  
  9. //提交事務  
  10. transaction.commit();
複製程式碼 解釋:newFragment代替了控制元件ID R.id.fragment_container所指向的ViewGroup中所含的任何fragment。然後呼叫addToBackStack(),此時被代替的fragment就被放入後退棧中,於是當用戶按下返回鍵時,事務發生回溯,原先的fragment又回來了。如果向事務添加了多個動作,比如多次呼叫了add(),remove()等之後又呼叫了addToBackStack()方法,那麼所有的在commit()之前呼叫的方法都被作為一個事務。當用戶按返回鍵時,所有的動作都被反向執行(事務回溯)。    
事務中動作的執行順序可隨意,但要注意以下幾點:<1> 必須最後呼叫commit();
<2> 如果添加了多個fragment,那麼它們的現實順序跟新增順序一致(後顯示的覆蓋前面的)<3> 如果在執行的事務中有刪除fragment的動作,而且沒有呼叫addToBackStack(),那麼當事務提交時,那些被刪除的fragment就被銷燬了。反之,那些fragment就不會被銷燬,而是處於停止狀態。當用戶返回時,它們會被恢復。
<4> 但是,呼叫commit()後,事務並不會馬上執行。它會在activity的UI執行緒(其實就是主執行緒)中等待直到現成能執行的時候才執行。如果必要,可以在UI執行緒中呼叫executePendingTransactions()方法來立即執行事務。但一般不需要這樣做,除非有其它執行緒在等待事務的執行。     注意:只能在activity處於可儲存狀態的狀態時,比如running中,onPause()方法和onStop()方法中提交事務,否則會引發異常。這是因為fragment的狀態會丟失。如果要在可能丟失狀態的情況下提交事務,請使用commitAllowingStateLoss()。 1.5 Fragment與Activity通訊            儘管fragment的實現是獨立於activity的,可以被用於多個activity,但是每個activity所包含的是同一個fragment的不同的例項。Fragment可以呼叫getActivity()方法很容易的得到它所在的activity的物件,然後查詢activity中的控制元件們(findViewById())。                有時,可能需要fragment與activity共享事件。一個好辦法是在fragment中定義一個回撥介面,然後在activity中實現之。例如,還是那個新聞程式的例子,它有一個activity,activity中含有兩個fragment。fragmentA顯示新聞標題,fragmentB現實標題對應的內容。fragmentA必須在使用者選擇了某個標題時告訴activity,然後activity再告訴fragmentB,fragmentB就顯示出對應的內容。  二、Fragment例項講解一 2.1 例項效果圖
點選“儲存”按鈕顯示的介面:
 點選wifi“按鈕”顯示的介面: 

2.2 專案結構
 2.3 具體程式碼編寫
1、左邊頁面佈局介面,frag_list.xml:
  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.     <TextView
  7.         android:layout_width="wrap_content"
  8.         android:layout_height="wrap_content"
  9.         android:text="無線和網路"
  10.         android:textSize="30sp" />
  11.     <TextView
  12.         android:layout_width="match_parent"
  13.         android:layout_height="1px"
  14.         android:background="@color/lineColor" />
  15.     <LinearLayout
  16.         android:layout_width="match_parent"
  17.         android:layout_height="wrap_content"
  18.         android:layout_gravity="center_vertical"
  19.         android:layout_marginLeft="10dp"
  20.         android:orientation="horizontal" >
  21.         <TextView
  22.             android:id="@+id/wifi"
  23.             android:layout_width="wrap_content"
  24.             android:layout_height="wrap_content"
  25.             android:layout_gravity="center_vertical"
  26.             android:text="WI-Fi"
  27.             android:textSize="30sp" />
  28.         <ToggleButton
  29.             android:id="@+id/toggleButton"
  30.             android:layout_width="wrap_content"
  31.             android:layout_height="wrap_content"
  32.             android:layout_gravity="center_vertical"
  33.             android:layout_marginLeft="20dp"
  34.             android:text="開" />
  35.     </LinearLayout>
  36.     <TextView
  37.         android:layout_width="match_parent"
  38.         android:layout_height="1px"
  39.         android:background="@color/lineColor" />
  40. 相關推薦

    Fragment詳細介紹使用方法案例

    由於TabActivity在Android4.0以後已經被完全棄用,那麼我就不再浪費口水繼續講解它了,取而代之的是Fragment。Fragment是Android3.0新增的概念,Fragment翻譯成中文是碎片的意思,不過卻和Activity十分的相似,這一篇我花

    form表單的應用:form對象自帶屬性方法提交時提交的數據.....

    uil nsf fileread tex class dataurl asd who accept 1.html中含有form表單 (1)html <form id="picLoad" class="lt" style="width: 230px;" enctype=

    HTML5的自定義屬性data-*詳細介紹JS操作實例

    select 文章 red data scrip style box 實例 width 這篇文章主要介紹JS操作HTML自定義屬性的方法, 以實例形式分析了html中自定義屬性的設置與對應的javascript操作技巧 具體如下: HTML代碼如下(其中的d

    淺析JavaScript訪問對象屬性方法區別

    cti on() 對象方法 編寫程序 因此 brush new 函數 name 屬性是一個變量,用來表示一個對象的特征,如顏色、大小、重量等;方法是一個函數,用來表示對象的操作,如奔跑、呼吸、跳躍等。 在JavaScript中通常使用”."運算符來存取對象的屬性的值。或者使

    一個簡單的執行程序的GNU automake自動生成Makefile的方法案例

    rect -o 創建 otool 其中 ner markdown ted head 一個簡單的執行程序的GNU automake自動生成Makefile的方法及案例 在GNU的世界裏,存在Automake這樣的工具進行自動生成Makefile文件,automake是由Per

    ajax請求解決方法案例

    nts scrip ava hsi extend cond 得到 als 使用   當前項目對用戶體驗的要求層出不窮,本篇通過所歷項目與前輩網文日誌加以記錄總結。   多個 ajax 請求的各類解決方案:同步,隊列,cancel 請求,本章末尾提供 demo,或點這裏。  

    Java ArrayList詳細介紹使用示例

    zab tco random class strong art vector 導致 執行 對ArrayList的整體認識 ArrayList是一個數組隊列,相當於動態數組。與Java中的數組相比,它的容量能動態增長。它繼承了AbstractList,實現了List,Rand

    Java HashMap詳細介紹使用示例(正在整理學習中)

    trac blog null https 學習 ava abs 同步 .com 對HashMap的整體認識 HashMap是一個散列表,它存儲的內容是鍵值對(key-value)映射。 HashMap繼承於AbstractMap,實現了Map、Cloneable、jav

    VMware網絡連接模式—橋接、NAT以及僅主機模式的詳細介紹區別.ziw

    splay post 80端口 linux style -c inf 物理 數量 2017年1月10日, 星期二 VMware網絡連接模式—橋接、NAT以及僅主機模式的詳細介紹和區別 在使用VMware Workstation(以下簡稱:VMware)創建虛擬機的過程中

    ViewPager的詳細介紹圖片滑動功能例項

    1、使用場景 在APP設計中,如果涉及到左右滑動功能,如:下方導航條、上方導航條、圖片滑動、翻頁能功能時,則可以直接使用ViewPager進行開發,ViewPager自帶滑動和翻頁效果,可以用ViewPager自身的adapter進行開發,要方便很多。 2、屬性詳解 ViewPage

    python各種操作列表的方法案例

    一、迴圈的使用方法 names = ["張真","劉德華","哈林","謝霆鋒","張柏芝"] for name in names: print("你好!"+ name) print("i love you" + name) 二、使用函式range(),配合迴圈輕鬆生成一組數字 #以下程式碼好像

    步進電機 28BYJ-48介紹驅動程式設計

    28BYJ-48步進電機: 步進電機是一種將電脈衝轉化為角位移的執行機構。通俗一點講:當步進驅動器接收到一個脈衝訊號,它就驅動步進電機按設定的方向轉動一個固定的角度(及步進角)。您可以通過控制脈衝個來控制角位移量,從而達到準確定位的目的;同時您可以通過控制脈衝頻

    springboot整合freemarker的具體方法案例

    1.pom依賴 <!-- 引入freeMarker的依賴包. --> <dependency> <groupId>org.springframework.boot</groupId>

    Scrapy入門教程之詳細介紹一個很好的例子

    Scrapy入門教程之詳細介紹和一個很好的例子 Scrapy,Python開發的一個快速、高層次的螢幕抓取和web抓取框架,用於抓取web站點並從頁面中提取結構化的資料。Scrapy用途廣泛,可以用於資料探勘、監測和自動化測試。 Scrapy吸引人的地方在於它是一個框架,任何人都可以根據

    【轉】ZooKeeper詳細介紹使用第一節

    一、分散式協調技術 在給大家介紹ZooKeeper之前先來給大家介紹一種技術——分散式協調技術。那麼什麼是分散式協調技術?那麼我來告訴大家,其實分散式協調技術 主要用來解決分散式環境當中多個程序之間的同步控制,讓他們有序的去訪問某種臨界資源,防止造成"髒資料"的後果。這時,有人可能會說這個簡單,寫一個調 度

    Fragment 詳細介紹(由來、靜態載入,動態載入,頁卡滑動切換)

    1.什麼是Fragment? Fragment的由來 基於Android系統的裝置越來越多,解析度種類越來越多,Google提出Fragment的概念也是希望通過Fragment解決螢幕碎片化問題。 Fragment的翻譯為碎片,自Android3.0開始引入Fragmen

    一個簡單的執行程式的GNU automake自動生成Makefile的方法案例

    1、autoscan 2、修改生成的configure.scan為configure.in 3、aclocal 4、autoheader 5、autoconf 6、建立Makefile.am並進行具體內容的寫入 7、automake 8、automake 9、./configure生成Makefile

    異常丟擲增強使用方法案例

    在說使用AOP面向切面程式設計的思想對程式碼段進行增強處理之前,先說兩個理論知識點: —常用切入表示式模糊匹配解釋: ①public * addUser(com.pb.entity.User): “*”表示匹配所有型別的返回值;  ②public void * (co

    javascript的getElementsByTagName()方法案例

    getElementsByTagName() 尋找有著給定標籤名的所有元素,這個方法將返回一個節點集合,這個集合可以當作一個數組來處理。這個集合的 length 屬性等於當前文件裡有著給定標籤名的所有元素的總個數。 var elements = document.getEl

    Git 詳細介紹使用

    開發十年,就只剩下這套架構體系了! >>>