Fragment碎片

Fragment 簡介

俗稱“碎片”,Android是在Android 3.0 (API level 11)開始引入Fragment的。
Fragment名為碎片不過卻和Activity十分相似,Fragment用來描述一些行為或一部分用戶界面在一個Activity中,你可以合并多個fragment在一個單獨的activity中建立多個UI面板,同時重用fragment在多個activity中.你可以認為fragment作為一個activity中的一節模塊 ,fragment有自己的生命周期,接收自己的輸入事件,你可以添加或移除從運行中的activity.
一個fragment必須總是嵌入在一個activity中,同時fragment的生命周期受activity而影響,舉個例子吧,當activity 暫停,那么所有在這個activity的fragments將被destroy釋放。然而當一個activity在運行比如resume時,你可以單獨的操控每個fragment,比如添加或刪除。

Fragment的兩個包app包中的fragment和v4包中的fragment的使用的區別

1,app包中的fragment,因為這個是在3.0之后才有的,支持的版本太高,在低版本中是是用不了的
android.support.v4.app.Fragment:可以兼容到1.6的版本。
2,關于這兩個fragment使用標簽的問題:
app.fragment和v4.fragment都是可以使用<fragment>標簽的,在布局中沒什么區別
當v4.fragment使用標簽的時候就要特別注意了:
當這個Activity要使用android.support.v4.app.Fragment的時候,這個Activity必須繼承FragmentActivity,否則就會報錯
Caused by: java.lang.ClassCastException: com.example.android_fragment_bottom.fragments.TopBarFragment cannot be cast to android.app.Fragment
此時如果不繼承FragmentActivity的話,編譯系統會把android.support.v4.app.Fragment當成app包中的Fragment來處理。但是此時我們導入的是v4包中的Fragment。
3,得到FragmentManager的方法不一樣
android.app.Fragment:使用getFragmentManager()方法
android.support.v4.app.Fragment:使用getSupportFragmentManager()方法

Fragment優點:

1,Fragment可以使你能夠將activity分離成多個可重用的組件,每個都有它自己的生命周期和UI。
2,Fragment可以輕松得創建動態靈活的UI設計,可以適應于不同的屏幕尺寸。從手機到平板電腦。
3,Fragment是一個獨立的模塊,緊緊地與activity綁定在一起。可以運行中動態地移除、加入、交換等。
4,Fragment提供一個新的方式讓你在不同的安卓設備上統一你的UI。
5,Fragment 解決Activity間的切換不流暢,輕量切換。
6,Fragment 替代TabActivity做導航,性能更好。
7,Fragment 在4.2.版本中新增嵌套fragmeng使用方法,能夠生成更好的界面效果。
8,Fragment做局部內容更新更方便,原來為了到達這一點要把多個布局放到一個activity里面,現在可以用多Fragment來代替,只有在需要的時候才加載Fragment,提高性能

Fragment 的生命周期:

先上一張Andorid API上關于Fragment的生命周期圖:

對比圖:
image.png

Fragment 圖

image

生命周期的經歷

  1. 當一個fragment被創建的時候,它會經歷以下狀態.
    onAttach()
    onCreate()
    onCreateView()
    onActivityCreated()
  2. 當這個fragment對用戶可見的時候,它會經歷以下狀態。
    onStart()
    onResume()
  3. 當這個fragment進入“后臺模式”的時候,它會經歷以下狀態。
    onPause()
    onStop()
  4. 當這個fragment被銷毀了(或者持有它的activity被銷毀了),它會經歷以下狀態。
    onPause()
    onStop()
    onDestroyView()
    onDestroy()
    onDetach()

下面對Fragment的每個生命周期方法以及與Activity的關聯進行詳細介紹:

1、onAttach()

這個時候 activity已經傳進來了, 獲得activity的傳遞的值 就可以進行 與activity的通信里, 當然也可以使用getActivity(),前提是這個fragment已經和宿主的activity關聯,并且沒有脫離,他只調用一次。注他還可以通過Activity參數強轉成上下文

2、onCreate()

系統創建fragment的時候回調。

3、onCreateView()

第一次使用的時候 fragment會在這上面畫一個layout出來, 要返回一個 布局的view,也可以返回null。盡量在這里不要做耗時操作,比如從數據庫加載大量數據顯示listview等。

4、onActivityCreated()

當Activity中的onCreate方法執行完后調用。

當執行onActivityCreated()的時候 activity的onCreate才剛完成,所以在onActivityCreated()調用之前 activity的onCreate可能還沒有完成,所以不能在onCreateView()中進行與activity有交互的UI操作,UI交互操作可以在onActivityCreated()里面進行。

5、onStart()

Fragment 啟動時回調,此時Fragment可見。

6、onResume()

獲取焦點時回調。

7、onPause()

失去焦點時回調。

8、onStop()

Fragment不可見時回調。

9、onDestroyView()

Fragment中的布局被移除時調用。表示fragemnt銷毀相關聯的UI布局, 清除所有跟視圖相關的資源。

10、onDestroy()

Fragment銷毀時回調。

11、onDetach()

Fragment與Activity解除關聯時回調。

activity和fragment同時運行時候的生命周期

oncreate

onAttach_Fragment

onCreate_Fragment

onCreateView_Fragment

onActivityCreated_Fragment

onStart

onStart_Fragment

onResume

onResume_Fragment

按下home按鍵

onPause_Fragment

onPause

onStop_Fragment

onStop

切換回前臺

onRestart

onStart

onStart_Fragment

onResume

onResume_Fragment

銷毀activity

onPause_Fragment

onPause

onStop_Fragment

onStop

onDestroyView_Fragment

onDestroy_Fragment

onDetach_Fragment

onDestroy

android.app.Fragment包下的

Fragment 的使用

1種是在布局中調用碎片id,width,height,name.通過name指定一個繼承了Fragment的類
2種在代碼中碎片替換布局,寫一個碎片類(要繼承Fragment),碎片類加載布局通過inflater.inflate方式加載布局然后return出他的返回值.
布局代碼中:

package com.example.fragment_text1;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {

    private FragmentManager manager;
    private Fragment_mymain mymain;
    private Fragment_go fragment_go;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        manager = getFragmentManager();// 獲取碎片管理者
        mymain = new Fragment_mymain();// 首頁
        fragment_go = new Fragment_go();// 購物
        // 一開始就是首頁
        open();
    }

    private void open() {
//鏈式調用
manager.beginTransaction().replace(R.id.layout_fragment, mymain).commit();
            

    }

    public void dian(View v) {
        open();
    }

    public void wo(View v) {
        // 開啟事務2
        FragmentTransaction beginTransaction = manager.beginTransaction();
        // 替換布局
        // 1,參數是要替換的布局
        // 2,參數是碎片類
        beginTransaction.replace(R.id.layout_fragment, fragment_go);
        // 提交事務
        beginTransaction.commit();

    }

    public void ya(View v) {

    }
}

主布局中.xml寫了一個要被替換的布局

<FrameLayout
        android:id="@+id/layout_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#999">
    </FrameLayout>

首頁碎片布局類,里面加載了布局,要繼承碎片哦

package com.example.fragment_text1;

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

public class Fragment_mymain extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View inflate = inflater.inflate(R.layout.layout_fragment, null);
    return inflate;
}
}

購物碎片布局類,里面加載了布局,,要繼承碎片哦

package com.example.fragment_text1;

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

public class Fragment_go extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View inflate = inflater.inflate(R.layout.fragment_go, null);
    return inflate;
}
}

效果圖可以完成一個切換效果

image.png

android.support.v4.app.包下的Fragment 的使用

主活動頁面要繼承FragmentActivity才能用getSupportFragmentManager支持碎片管理器,向里面添加或替換的碎片類都繼承import android.support.v4.app.Fragment;包下的Fragment
其他的添加和切換的方式和上面的一樣,有點就是支持版本1.6

Fragment 的使用2

使用add,和show,hide可以保留痕跡:因他是添加而不是上面的替換
在oncreter里面我寫了

        manager = getFragmentManager();//獲取碎片管理器
        mymain = new Fragment_mymain();// 首頁
        fragment_go = new Fragment_go();// 購物
        transaction = manager.beginTransaction();//開啟服務
        transaction.add(R.id.hehe, mymain);//添加碎片,同樣的注碎片只能添加一次
        transaction.add(R.id.hehe, fragment_go);
        transaction.commit();//開啟一次服務就要提交一次

然后在點擊事件中寫

transaction = manager.beginTransaction();//開啟
    transaction.show(mymain);//顯示碎片
    transaction.hide(fragment_go);//隱藏碎片
transaction.commit();//提交

關于xml布局中Fragment與 FrameLayout的理解(動態替換的Fragment,為什么替換的布局是FrameLayout?)?

FrameLayout與Fragment標簽都是用來放Fragment的,區別是,Fragment標簽只能設置固定的Fragment,而FrameLayout中可以通過FragmentManager更換Fragment
注他A布局被替換之后他的屬性和方法會在B替換碎片布局的身上

用fragment 替換 布局中的LinearLayout,然后如何換回來???

可以用.remove() 從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧后面會詳細說),這個Fragment實例將會被銷毀。

兩個Fragment之間如何傳遞數據?

訪問:http://www.cnblogs.com/graphics/p/5151547.html

默認開始碎片布局是最后添加的布局

Fragment add replace 區別?

用法上add配合hide或是remove使用,replace一般單獨出現。
注:mymain進行了操作切換他自己時mymain里面的數據不會被干掉(因為我在oncreate中new了一次)
當切換成其他碎片的時候就會把mymain給干掉換成fragment_go

如何隔類add show hide remove

就要給add方法添加第三個參數是tag
show 和 hide ,remove 通過管理者.findFragmentTag("來制定碎片")

1、activity--->碎片
(1)如果碎片是通過xml文件生成的
    直接通過findViewById獲取到碎片中的控件,然后給控件設置內容。
(2)如果碎片是通過代碼生成的
     activity中添加碎片的時候,通過碎片對象的.setArgments(bundle)
     在fragment里面,通過getArgments()得到一個bundle對象,再從bundle對象里面獲取內容

 2、碎片--->activity
     在activity中聲明一個公共的方法,在這個方法中必須要有一個參數(參數類型就是要傳遞的數據類型)
     在fragment里面,通過getActivity(),可以獲取到宿主activity對象,再調用宿主對象中提供的公共方法,
             把數據傳遞在這個方法中。

     獲取assets目錄中的文件流的方法:getActivity().getAssets().open("day10.txt");

 3、碎片--->碎片        
        先把一個碎片里的值傳到它的宿主activity,再從宿主activity傳到另一個碎片。
 注意:
        如果碎片中有按鈕,那么按鈕的點擊事件只能用監聽器的方式綁定,不能用屬性onClick

碎片傳遞數據

發送
// 在Fragment1中創建Fragment2的實例
Fragment2  fragment2 = new Fragment2();
Bundle bundle = new Bundle();
// 傳遞實體類,需要實體類實現Serializable接口
bundle.putSerializable("key_entity", value_Entity);
// 傳遞字符串
bundle.putString("key_str",value_str);
// 傳遞int類型數
bundle.putInt("key_int",value_int);
//設置數據
fragment2.setArgument(bundle);
//調用上面的方法由 fragment1 跳轉到 fragment2
showFragment(Fragment1.this, fragment2);

獲取
// 獲取由碎片1傳遞過來的實體類數據
Value_Entity value_Entity = (Value_Entity)getArgument.getSerializable("key_entity");
// 獲取由碎片1傳遞過來的String類型數據
String value_str = (String)getArgument.getString("key_str");
// 獲取由碎片1傳遞過來的int類型數據
int value_int = (String)getArgument.getInt("key_int");
}

View inflate = inflater.inflate(R.layout.fragment_xiaoxi, container, false);

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容