天天看點

Android--Fragment基本介紹

  可以把fragment想成activity中的子產品,這個子產品有自己的布局,有自己的生命周期,單獨處理自己的輸入,在activity運作的時候可以加載或者移除fragment子產品。

  可以把fragment設計成可以在多個activity中複用的子產品。

  當開發的應用程式同時适用于平闆電腦和手機時,可以利用fragment實作靈活的布局,改善使用者體驗。

  如圖:

Android--Fragment基本介紹

  因為fragment必須嵌入在acitivity中使用,是以fragment的生命周期和它所在的activity是密切相關的。

  如果activity是暫停狀态,其中所有的fragment都是暫停狀态;如果activity是stopped狀态,這個activity中所有的fragment都不能被啟動;如果activity被銷毀,那麼它其中的所有fragment都會被銷毀。

  但是,當activity在活動狀态,可以獨立控制fragment的狀态,比如加上或者移除fragment。

  當這樣進行fragment transaction(轉換)的時候,可以把fragment放入activity的back stack中,這樣使用者就可以進行傳回操作。

Android--Fragment基本介紹

可以看到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好幹淨有木有~~代碼的可讀性、複用性以及可維護性是不是瞬間提升了~~~下面看下效果圖:

Android--Fragment基本介紹

上面已經示範了,最簡單的使用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);  

效果圖:

Android--Fragment基本介紹

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

繼續閱讀