可以把fragment想成activity中的子產品,這個子產品有自己的布局,有自己的生命周期,單獨處理自己的輸入,在activity運作的時候可以加載或者移除fragment子產品。
可以把fragment設計成可以在多個activity中複用的子產品。
當開發的應用程式同時适用于平闆電腦和手機時,可以利用fragment實作靈活的布局,改善使用者體驗。
如圖:

因為fragment必須嵌入在acitivity中使用,是以fragment的生命周期和它所在的activity是密切相關的。
如果activity是暫停狀态,其中所有的fragment都是暫停狀态;如果activity是stopped狀态,這個activity中所有的fragment都不能被啟動;如果activity被銷毀,那麼它其中的所有fragment都會被銷毀。
但是,當activity在活動狀态,可以獨立控制fragment的狀态,比如加上或者移除fragment。
當這樣進行fragment transaction(轉換)的時候,可以把fragment放入activity的back stack中,這樣使用者就可以進行傳回操作。
可以看到fragment比activity多了幾個額外的生命周期回調方法:
onattach(activity)
當fragment與activity發生關聯時調用。
oncreateview(layoutinflater, viewgroup,bundle)
建立該fragment的視圖
onactivitycreated(bundle)
當activity的oncreate方法傳回時調用
ondestoryview()
與oncreateview想對應,當該fragment的視圖被移除時調用
ondetach()
與onattach相對應,當fragment與activity關聯被取消時調用
注意:除了oncreateview,其他的所有方法如果你重寫了,必須調用父類對于該方法的實作,
嘿嘿,終于到使用的時刻了~~
這是使用fragment最簡單的一種方式,把fragment當成普通的控件,直接寫在activity的布局檔案中。步驟:
1、繼承fragment,重寫oncreateview決定fragemnt的布局
2、在activity中聲明此fragment,就當和普通的view一樣
下面展示一個例子(我使用2個fragment作為activity的布局,一個fragment用于标題布局,一個fragment用于内容布局):
titlefragment的布局檔案:
<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@drawable/title_bar" >
<imagebutton
android:id="@+id/id_title_left_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centervertical="true"
android:layout_marginleft="3dp"
android:background="@drawable/showleft_selector" />
<textview
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:text="我不是微信"
android:textcolor="#fff"
android:textsize="20sp"
android:textstyle="bold" />
</relativelayout>
titlefragment
package com.zhy.zhy_fragments;
import android.app.fragment;
import android.os.bundle;
import android.view.layoutinflater;
import android.view.view;
import android.view.view.onclicklistener;
import android.view.viewgroup;
import android.widget.imagebutton;
import android.widget.toast;
public class titlefragment extends fragment
{
private imagebutton mleftmenu;
@override
public view oncreateview(layoutinflater inflater, viewgroup container,
bundle savedinstancestate)
{
view view = inflater.inflate(r.layout.fragment_title, container, false);
mleftmenu = (imagebutton) view.findviewbyid(r.id.id_title_left_btn);
mleftmenu.setonclicklistener(new onclicklistener()
{
@override
public void onclick(view v)
{
toast.maketext(getactivity(),
"i am an imagebutton in titlefragment ! ",
toast.length_short).show();
}
});
return view;
}
}
同理還有contentfragment的其布局檔案:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:orientation="vertical" >
android:text="使用fragment做主面闆"
</linearlayout>
public class contentfragment extends fragment
return inflater.inflate(r.layout.fragment_content, container, false);
mainactivity
import android.app.activity;
import android.view.window;
public class mainactivity extends activity
protected void oncreate(bundle savedinstancestate)
super.oncreate(savedinstancestate);
requestwindowfeature(window.feature_no_title);
setcontentview(r.layout.activity_main);
activity的布局檔案:
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent" >
<fragment
android:id="@+id/id_fragment_title"
android:name="com.zhy.zhy_fragments.titlefragment"
android:layout_height="45dp" />
android:layout_below="@id/id_fragment_title"
android:id="@+id/id_fragment_content"
android:name="com.zhy.zhy_fragments.contentfragment"
android:layout_height="fill_parent" />
是不是把fragment當成普通的view一樣聲明在activity的布局檔案中,然後所有控件的事件處理等代碼都由各自的fragment去處理,瞬間覺得activity好幹淨有木有~~代碼的可讀性、複用性以及可維護性是不是瞬間提升了~~~下面看下效果圖:
上面已經示範了,最簡單的使用fragment的方式~下面介紹如何動态的添加、更新、以及删除fragment
<include
android:id="@+id/id_ly_bottombar"
android:layout_height="55dp"
android:layout_alignparentbottom="true"
layout="@layout/bottombar" />
<framelayout
android:id="@+id/id_content"
android:layout_above="@id/id_ly_bottombar"
android:layout_below="@id/id_fragment_title" />
底部四個按鈕的布局就不貼了,到時看效果圖就明白了~~
下面主activity
import android.app.fragmentmanager;
import android.app.fragmenttransaction;
import android.widget.linearlayout;
public class mainactivity extends activity implements onclicklistener
private linearlayout mtabweixin;
private linearlayout mtabfriend;
private contentfragment mweixin;
private friendfragment mfriend;
// 初始化控件和聲明事件
mtabweixin = (linearlayout) findviewbyid(r.id.tab_bottom_weixin);
mtabfriend = (linearlayout) findviewbyid(r.id.tab_bottom_friend);
mtabweixin.setonclicklistener(this);
mtabfriend.setonclicklistener(this);
// 設定預設的fragment
setdefaultfragment();
private void setdefaultfragment()
fragmentmanager fm = getfragmentmanager();
fragmenttransaction transaction = fm.begintransaction();
mweixin = new contentfragment();
transaction.replace(r.id.id_content, mweixin);
transaction.commit();
public void onclick(view v)
// 開啟fragment事務
switch (v.getid())
case r.id.tab_bottom_weixin:
if (mweixin == null)
mweixin = new contentfragment();
// 使用目前fragment的布局替代id_content的控件
transaction.replace(r.id.id_content, mweixin);
break;
case r.id.tab_bottom_friend:
if (mfriend == null)
mfriend = new friendfragment();
transaction.replace(r.id.id_content, mfriend);
}
// transaction.addtobackstack();
// 事務送出
可以看到我們使用fragmentmanager對fragment進行了動态的加載,這裡使用的是replace方法~~下一節我會詳細介紹fragmentmanager的常用api。
注:如果使用android3.0以下的版本,需要引入v4的包,然後activity繼承fragmentactivity,然後通過getsupportfragmentmanager獲得fragmentmanager。不過還是建議版menifest檔案的uses-sdk的minsdkversion和targetsdkversion都改為11以上,這樣就不必引入v4包了。
代碼中間還有兩個fragment的子類,contentfragment上面已經見過,friendfragment其實類似:
public class friendfragment extends fragment
return inflater.inflate(r.layout.fragment_friend, container, false);
效果圖:
fragment常用的三個類:
android.app.fragment 主要用于定義fragment
android.app.fragmentmanager 主要用于在activity中操作fragment
android.app.fragmenttransaction 保證一些列fragment操作的原子性,熟悉事務這個詞,一定能明白~
a、擷取fragmentmanage的方式:
getfragmentmanager() // v4中,getsupportfragmentmanager
b、主要的操作都是fragmenttransaction的方法
fragmenttransaction transaction = fm.bengintransatcion();//開啟一個事務
transaction.add()
往activity中添加一個fragment
transaction.remove()
從activity中移除一個fragment,如果被移除的fragment沒有添加到回退棧(回退棧後面會詳細說),這個fragment執行個體将會被銷毀。
transaction.replace()
使用另一個fragment替換目前的,實際上就是remove()然後add()的合體~
transaction.hide()
隐藏目前的fragment,僅僅是設為不可見,并不會銷毀
transaction.show()
顯示之前隐藏的fragment
detach()
會将view從ui中移除,和remove()不同,此時fragment的狀态依然由fragmentmanager維護。
attach()
重建view視圖,附加到ui上并顯示。
transatcion.commit()//送出一個事務
注意:常用fragment的哥們,可能會經常遇到這樣activity狀态不一緻:state loss這樣的錯誤。主要是因為:commit方法一定要在activity.onsaveinstance()之前調用。
上述,基本是操作fragment的所有的方式了,在一個事務開啟到送出可以進行多個的添加、移除、替換等操作。
值得注意的是:如果你喜歡使用fragment,一定要清楚這些方法,哪個會銷毀視圖,哪個會銷毀執行個體,哪個僅僅隻是隐藏,這樣才能更好的使用它們。
a、比如:我在fragmenta中的edittext填了一些資料,當切換到fragmentb時,如果希望會到a還能看到資料,則适合你的就是hide和show;也就是說,希望保留使用者操作的面闆,你可以使用hide和show,當然了不要使勁在那new執行個體,進行下非null判斷。
b、再比如:我不希望保留使用者操作,你可以使用remove(),然後add();或者使用replace()這個和remove,add是相同的效果。
c、remove和detach有一點細微的差別,在不考慮回退棧的情況下,remove會銷毀整個fragment執行個體,而detach則隻是銷毀其視圖結構,執行個體并不會被銷毀。那麼二者怎麼取舍使用呢?如果你的目前activity一直存在,那麼在不希望保留使用者操作的時候,你可以優先使用detach。
上述已經介紹完成了fragment常用的一些方法,相信看完,大家一定清楚了fragment的産生理由,以及如何使用fragment,再根據api的講解,也能明白,曾經為何覺得fragment會出現一些列亂七八槽的問題,終究是因為沒有弄清楚其生命周期。
由于篇幅原因,剩下的内容留到下一篇了。在下一篇,會介紹:
1、如何管理fragment回退棧
2、fragment如何與activity互動
3、fragment與activity互動的最佳實踐
4、沒有視圖的fragment的用處
5、使用fragment建立對話框
6、如何與actionbar,menuitem內建等
轉載:http://blog.csdn.net/chaoyu168/article/details/51191389