天天看點

利用Fragment實作仿微信Tab效果(Fragment的初步學習)

在前一次利用ViewPager實作仿微信Tab效果的後,又學習了利用Fragment實作該效果,剛好是對Fragment的一次學習了解。

效果圖就不展示了,和ViewPager的界面類似,唯一的缺點就是,利用單純的Fragment無法實作像ViewPager一樣的左右滑切換。就當做一次對Fragment的了解學習吧。

這個Demo的難點總結:

1.Fragment的了解與使用。

2.FragmentTransaction與Fragment生命周期的關系。

3.FragmentTransaction中不同操作的差別。(此處遇到問題!)

接下來來詳細闡述一下以上兩點:

一、Fragment的了解使用。

原來一直都是在書上看完了Fragment的使用,隻是知道Fragment的是用來在一個Activity中便于實作大量控件與事件的分類處理。利用這次機會剛好初步學習了一下Fragment的使用與了解。

http://blog.csdn.net/lmj623565791/article/details/37970961這篇大神的部落格已經很詳細的講解了有關Fragment的了解與使用。看完過後知道了Fragment的基礎使用方式兩種:

(1)靜态的使用Fragment

(2)動态的使用Fragment。

而本例中使用的就是第二種使用方式,利用FragmentTransaction實作動态使用Fragment。一開始還不了解動态的使用的含義,看完那篇部落格後,了解到,就是利用FragmentManager在Activity中操作Fragment。

也就是說在Activity中動态的管理Fragment。具體方式步驟如下:

1.定義自己的mFragment繼承Fragment(此處有一個要點就是:包名要一緻,如果導入的是android.app.Fragment後面導入的都要是app下的包例如android.app.FragmentManager;而如果導入的是android.support.v4.app.Fragment,後面要一緻導入v4包,不然會産生錯誤)。重寫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。

3.開啟一個事務FragmentTransaction。

4.調用add(),show(),remove(),replace(),hide()等相關操作實作所需功能。

代碼如下:

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();
    }
    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 :
            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 :
            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 :
            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 :
            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();
            break;
        case R.id.lin2:
            setSelect();
            break;
        case R.id.lin3:
            setSelect();
            break;
        case R.id.lin4:
            setSelect();
            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>
           

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

以上就是這次所有的總結,這樣就結束了嗎?NO!NO!NO!

在這個例子中一個無意的操作引發了一個自己無法解決的問題。

問題如下:

在這個例子中原理就是,每次點選之前都回執行hideFragment()方法使用者将所有的Fragment利用transaction.hide()方法隐藏掉,然後再二次點選時利用show()方法顯示。這些看似很基礎,但是我一開始寫的時候,不小心将hide()方法寫成了remove()方法,這時候問題來了!!!運作效果是第一次點選都是好的,但是第二次點選後界面就為空白了。

問題原因:

設定斷點調試,發現原因很簡單,執行remove後,二次點選在這一步:

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

這時f1不為null,執行show()方法,而f1已經被remove了是以show是空白。

但是看似簡單的問題原因,仔細一想,FragmentTransaction的remove方法定義是從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧後面會詳細說),這個Fragment執行個體将會被銷毀。

銷毀?對,你沒有看錯,銷毀後不應該為null嗎?為什麼判斷的時候不是null哪?糾結啊,看了Fragment的源碼和FragmentTransaction的源碼還是無法了解原因,Tag了Fragment的生命周期發現,remove後确實執行了onDetach()方法,也就是說該Fragment已經的确被銷毀了,但是判null的時候不是null,糾結啊!!!希望有大神能解決這個問題啊。我自己也在尋找原因,希望下次部落格能夠發出解決貼吧!

繼續閱讀