利用Fragment實(shí)現(xiàn)仿微信Tab效果(Fragment的初步學(xué)習(xí))

在前一次利用ViewPager實(shí)現(xiàn)仿微信Tab效果的后工育,又學(xué)習(xí)了利用Fragment實(shí)現(xiàn)該效果,剛好是對Fragment的一次學(xué)習(xí)理解冯痢。

效果圖就不展示了呜师,和ViewPager的界面類似,唯一的缺點(diǎn)就是双炕,利用單純的Fragment無法實(shí)現(xiàn)像ViewPager一樣的左右滑切換狞悲。就當(dāng)做一次對Fragment的理解學(xué)習(xí)吧。
這個Demo的難點(diǎn)總結(jié):
1.Fragment的理解與使用妇斤。
2.FragmentTransaction與Fragment生命周期的關(guān)系摇锋。
3.FragmentTransaction中不同操作的區(qū)別。(此處遇到問題U境)

接下來來詳細(xì)闡述一下以上兩點(diǎn):
一荸恕、Fragment的理解使用。
原來一直都是在書上看完了Fragment的使用死相,只是知道Fragment的是用來在一個Activity中便于實(shí)現(xiàn)大量控件與事件的分類處理融求。利用這次機(jī)會剛好初步學(xué)習(xí)了一下Fragment的使用與理解。
http://blog.csdn.net/lmj623565791/article/details/37970961這篇大神的博客已經(jīng)很詳細(xì)的講解了有關(guān)Fragment的理解與使用算撮∷簦看完過后知道了Fragment的基礎(chǔ)使用方式兩種:
(1)靜態(tài)的使用Fragment
(2)動態(tài)的使用Fragment。
而本例中使用的就是第二種使用方式钮惠,利用FragmentTransaction實(shí)現(xiàn)動態(tài)使用Fragment。一開始還不理解動態(tài)的使用的含義七芭,看完那篇博客后素挽,了解到,就是利用FragmentManager在Activity中操作Fragment狸驳。
也就是說在Activity中動態(tài)的管理Fragment预明。具體方式步驟如下:
1.定義自己的mFragment繼承Fragment(此處有一個要點(diǎn)就是:包名要一致缩赛,如果導(dǎo)入的是android.app.Fragment后面導(dǎo)入的都要是app下的包例如android.app.FragmentManager;而如果導(dǎo)入的是android.support.v4.app.Fragment撰糠,后面要一致導(dǎo)入v4包酥馍,不然會產(chǎn)生錯誤)。重寫onCreateView方法:如下

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Log.i("Tag", "onCreateView");
    // TODO Auto-generated method stub
    return inflater.inflate(R.layout.tab1, container, false);
}

2.獲取FragmentManage阅酪,利用getFragmentManager()(v4中旨袒,getSupportFragmentManager)得到FragmentManage。

FragmentManager fm = getFragmentManager();

3.開啟一個事務(wù)FragmentTransaction术辐。

FragmentTransaction transaction = fm.beginTransaction();

4.調(diào)用add(),show(),remove(),replace(),hide()等相關(guān)操作實(shí)現(xiàn)所需功能砚尽。

代碼如下:
MainActivity.java

package com.example.fragmenttab;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity implements OnClickListener{
    private LinearLayout l1, l2, l3, l4;
    private ImageView pic1, pic2, pic3, pic4;
    private Fragment f1,f2,f3,f4;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
        setSelect(0);
    }
    private void initEvent() {
        // TODO Auto-generated method stub
        l1.setOnClickListener(this);
        l2.setOnClickListener(this);
        l3.setOnClickListener(this);
        l4.setOnClickListener(this);
    }

    private void initView() {
        // TODO Auto-generated method stub
        l1 = (LinearLayout) findViewById(R.id.lin1);
        l2 = (LinearLayout) findViewById(R.id.lin2);
        l3 = (LinearLayout) findViewById(R.id.lin3);
        l4 = (LinearLayout) findViewById(R.id.lin4);
        pic1 = (ImageView) findViewById(R.id.pic1);
        pic2 = (ImageView) findViewById(R.id.pic2);
        pic3 = (ImageView) findViewById(R.id.pic3);
        pic4 = (ImageView) findViewById(R.id.pic4);
    }
    private void setSelect(int i){
        FragmentManager fm = getFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        hideFragment(transaction);
        switch (i) {
        case 0:
            if(f1 == null){
                f1 = new OneFragment();
                transaction.add(R.id.content, f1);
            }else{
                transaction.show(f1);
            }
            pic1.setImageResource(R.drawable.tab_weixin_pressed);
            break;
        case 1:
            if(f2 == null){
                f2 = new SecondFragment();
                transaction.add(R.id.content, f2);
            }else{
                transaction.show(f2);
            }
            pic2.setImageResource(R.drawable.tab_find_frd_pressed);
            break;
        case 2:
            if(f3 == null){
                f3 = new ThirdFragment();
                transaction.add(R.id.content, f3);
            }else{
                transaction.show(f3);
            }
            pic3.setImageResource(R.drawable.tab_address_pressed);
            break;
        case 3:
            if(f4== null){
                f4 = new FourthFragment();
                transaction.add(R.id.content, f4);
            }else{
                transaction.show(f4);
            }
            pic4.setImageResource(R.drawable.tab_settings_pressed);
            break;
        }
        transaction.commit();
    }
    private void hideFragment(FragmentTransaction transaction) {
        //隱藏所有Fragment
        if(f1 != null){
            transaction.hide(f1);
        }
        if(f2 != null){
            transaction.hide(f2);
        }
        if(f3 != null){
            transaction.hide(f3);
        }
        if(f4 != null){
            transaction.hide(f4);
        }
    }
    @Override
    public void onClick(View v) {
        resetImage();
        switch (v.getId()) {
        case R.id.lin1:
            setSelect(0);
            break;
        case R.id.lin2:
            setSelect(1);
            break;
        case R.id.lin3:
            setSelect(2);
            break;
        case R.id.lin4:
            setSelect(3);
            break;
        }
    }

    private void resetImage() {
        // 重置所有圖片
        pic1.setImageResource(R.drawable.tab_weixin_normal);
        pic2.setImageResource(R.drawable.tab_find_frd_normal);
        pic3.setImageResource(R.drawable.tab_address_normal);
        pic4.setImageResource(R.drawable.tab_settings_normal);
    }
}

OneFragment.java

package com.example.fragmenttab;


import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class OneFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Log.i("Tag", "onCreateView");
    // TODO Auto-generated method stub
    return inflater.inflate(R.layout.tab1, container, false);
}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <include layout="@layout/top" />
    <FrameLayout 
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></FrameLayout>
    <include layout="@layout/bottom" />
</LinearLayout>

其他界面和前一個例子相同。

以上就是這次所有的總結(jié)辉词,這樣就結(jié)束了嗎必孤?NO!NO!NO!
在這個例子中一個無意的操作引發(fā)了一個自己無法解決的問題。
問題如下:
在這個例子中原理就是瑞躺,每次點(diǎn)擊之前都回執(zhí)行hideFragment()方法用戶將所有的Fragment利用transaction.hide()方法隱藏掉敷搪,然后再二次點(diǎn)擊時利用show()方法顯示。這些看似很基礎(chǔ)幢哨,但是我一開始寫的時候赡勘,不小心將hide()方法寫成了remove()方法,這時候問題來了V雒础Jê!運(yùn)行效果是第一次點(diǎn)擊都是好的曼振,但是第二次點(diǎn)擊后界面就為空白了几迄。
問題原因:
設(shè)置斷點(diǎn)調(diào)試,發(fā)現(xiàn)原因很簡單冰评,執(zhí)行remove后映胁,二次點(diǎn)擊在這一步:

if(f1 == null){
                f1 = new OneFragment();
                transaction.add(R.id.content, f1);
            }else{
                transaction.show(f1);
            }

這時f1不為null,執(zhí)行show()方法甲雅,而f1已經(jīng)被remove了所以show是空白解孙。
但是看似簡單的問題原因,仔細(xì)一想抛人,F(xiàn)ragmentTransaction的remove方法定義是從Activity中移除一個Fragment弛姜,如果被移除的Fragment沒有添加到回退棧(回退棧后面會詳細(xì)說),這個Fragment實(shí)例將會被銷毀妖枚。
銷毀廷臼?對,你沒有看錯,銷毀后不應(yīng)該為null嗎荠商?為什么判斷的時候不是null哪寂恬?糾結(jié)啊,看了Fragment的源碼和FragmentTransaction的源碼還是無法理解原因莱没,Tag了Fragment的生命周期發(fā)現(xiàn)初肉,remove后確實(shí)執(zhí)行了onDetach()方法,也就是說該Fragment已經(jīng)的確被銷毀了饰躲,但是判null的時候不是null,糾結(jié)把烙健!J籼眠寿!希望有大神能解決這個問題啊。我自己也在尋找原因焦蘑,希望下次博客能夠發(fā)出解決貼吧盯拱!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市例嘱,隨后出現(xiàn)的幾起案子狡逢,更是在濱河造成了極大的恐慌,老刑警劉巖拼卵,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奢浑,死亡現(xiàn)場離奇詭異,居然都是意外死亡腋腮,警方通過查閱死者的電腦和手機(jī)雀彼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來即寡,“玉大人徊哑,你說我怎么就攤上這事〈细唬” “怎么了莺丑?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長墩蔓。 經(jīng)常有香客問我梢莽,道長,這世上最難降的妖魔是什么奸披? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任昏名,我火速辦了婚禮,結(jié)果婚禮上阵面,老公的妹妹穿的比我還像新娘葡粒。我一直安慰自己份殿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布嗽交。 她就那樣靜靜地躺著,像睡著了一般颂斜。 火紅的嫁衣襯著肌膚如雪夫壁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天沃疮,我揣著相機(jī)與錄音盒让,去河邊找鬼。 笑死司蔬,一個胖子當(dāng)著我的面吹牛邑茄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俊啼,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肺缕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了授帕?” 一聲冷哼從身側(cè)響起同木,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎跛十,沒想到半個月后彤路,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芥映,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年洲尊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奈偏。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡坞嘀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出霎苗,到底是詐尸還是另有隱情姆吭,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布唁盏,位于F島的核電站内狸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏厘擂。R本人自食惡果不足惜昆淡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刽严。 院中可真熱鬧昂灵,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撑螺,卻和暖如春含思,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甘晤。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工含潘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人线婚。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓遏弱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塞弊。 傳聞我的和親對象是個殘疾皇子漱逸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容