Android系列之Fragment(一)----Fragment加載到Activity當中

【聲明】 html

歡迎轉載,但請保留文章原始出處→_→ java

生命壹號:http://www.cnblogs.com/smyhvae/ android

文章來源:http://www.cnblogs.com/smyhvae/p/3978989.htmlapp

 

【正文】ide

Android上的界面展現都是經過Activity實現的,Activity實在是太經常使用了。可是Activity也有它的侷限性,一樣的界面在手機上顯示可能很好看,在平板上就未必了,由於平板的屏幕很是大,手機的界面放在平板上可能會有過度被拉長、控件間距過大等狀況。這個時候更好的體驗效果是在Activity中嵌入"小Activity",而後每一個"小Activity"又能夠擁有本身的佈局。所以,咱們今天的主角Fragment登場了。模塊化

1、Fragment初探:佈局

Fragment是activity的界面中的一部分或一種行爲。你能夠把多個Fragment們組合到一個activity中來建立一個多面界面,而且你能夠在多個activity中重用一個Fragment。你能夠把Fragment認爲模塊化的一段activity,它具備本身的生命週期,接收它本身的事件,並能夠在activity運行時被添加或刪除。spa

Fragment不能獨立存在,它必須嵌入到activity中,並且Fragment的生命週期直接受所在的activity的影響。例如:當activity暫停時,它擁有的全部的Fragment們都暫停了,當activity銷燬時,它擁有的全部Fragment們都被銷燬。然而,當activity運行時(在onResume()以後,onPause()以前),你能夠單獨地操做每一個Fragment,好比添加或刪除它們。當你在執行上述針對Fragment的事務時,你能夠將事務添加到一個棧中,這個棧被activity管理,棧中的每一條都是一個Fragment的一次事務。有了這個棧,就能夠反向執行Fragment的事務,這樣就能夠在Fragment級支持「返回」鍵(向後導航)。設計

當向activity中添加一個Fragment時,它須置於ViewGroup控件中,而且需定義Fragment本身的界面。你能夠在layoutxml文件中聲明Fragment,元素爲:<fragment>;也能夠在代碼中建立Fragment,而後把它加入到ViewGroup控件中。然而,Fragment不必定非要放在activity的界面中,它能夠隱藏在後臺爲actvitiy工做。code

設計的哲學:

爲了讓界面能夠在平板上更好地展現,Android在3.0版本引入了Fragment(碎片)功能,經過官方文檔中的這張圖片能夠很明顯地看到Fragment的好處:

注:左邊爲平板,右邊爲手持設備。

 

2、Fragment的生命週期:

由於Fragment必須嵌入在Acitivity中使用,因此Fragment的生命週期和它所在的Activity是密切相關的。

若是Activity是暫停狀態,其中全部的Fragment都是暫停狀態;若是Activity是stopped狀態,這個Activity中全部的Fragment都不能被啓動;若是Activity被銷燬,那麼它其中的全部Fragment都會被銷燬。

可是,當Activity在活動狀態,能夠獨立控制Fragment的狀態,好比加上或者移除Fragment。

當這樣進行fragment transaction(轉換)的時候,能夠把fragment放入Activity的back stack中,這樣用戶就能夠進行返回操做。

使用Fragment時,須要繼承Fragment或者Fragment的子類(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),因此Fragment的代碼看起來和Activity的相似。

每當建立一個Fragment時,首先添加如下三個回調方法:

  • onCreate():系統在建立Fragment的時候調用這個方法,這裏應該初始化相關的組件,一些即使是被暫停或者被中止時依然須要保留的東西。
  • onCreateView():當第一次繪製Fragment的UI時系統調用這個方法,該方法將返回一個View,若是Fragment不提供UI也能夠返回null。注意,若是繼承自ListFragment,onCreateView()默認的實現會返回一個ListView,因此不用本身實現。
  • onPause():當用戶離開Fragment時第一個調用這個方法,須要提交一些變化,由於用戶極可能再也不返回來。

將Fragment加載到Activity當中有兩種方式:

  • 方式一:添加Fragment到Activity的佈局文件當中
  • 方式二:在Activity的代碼中動態添加Fragment

第一種方式雖然簡單但靈活性不夠。添加Fragment到Activity的佈局文件當中,就等同於將Fragment及其視圖與activity的視圖綁定在一塊兒,且在activity的生命週期過程當中,沒法切換fragment視圖。

第二種方式比較複雜,但也是惟一一種能夠在運行時控制fragment的方式(加載、移除、替換

下面將分別介紹一下。

  

3、在Activity的佈局文件中添加Fragment(不推薦)

平板的模擬器參數以下:

而後新建一個工程文件。而後繼續以下步驟:

(1)新建文件fragment_hello.xml和HelloFragment.java:

fragment_hello.xml代碼以下:(即Fragment的佈局文件)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <EditText 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入內容"/>
    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

 

HelloFragment.java代碼以下:

 1 package com.example.m01_fragment01;
 2 
 3 import android.app.Fragment;
 4 import android.os.Bundle;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 
 9 public class HelloFragment extends Fragment {
10     
11     @Override
12     public void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14     }
15     
16     @Override
17     public View onCreateView(LayoutInflater inflater, ViewGroup container,
18             Bundle savedInstanceState) {
19         View view = inflater.inflate(R.layout.fragment_hello, null);  // View android.view.LayoutInflater.inflate(int resource, ViewGroup root) 
20         return view; 21     }
22     
23     @Override
24     public void onPause() {
25         super.onPause();
26     }
27 }

重點在於第19和20行,經過inflate()方法將自定義的fragment的佈局加載進來。

19行代碼中,第二個參數中,若是佈局沒有根,那就用null。

注:上方代碼中,由於咱們的程序是面對Android 4.0以上版本的,因此導入Fragment的包時,選擇第一個:android.app.Fragment

(2)將Fragment添加到Activity的佈局中:

修改activity_main.xml的代碼以下:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context=".MainActivity" >
 6 
 7     <fragment
 8         android:id="@+id/fragment_hello"
 9  android:name="com.example.m01_fragment02.HelloFragment"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content" />
12 </LinearLayout>

08行和09行是關鍵。其中android:name屬性填上你本身建立的fragment的完整類名。以下圖:

當系統建立這個Activity的佈局文件時,系統會實例化每個fragment,而且調用它們的onCreateView()方法,來得到相應fragment的佈局,並將返回值插入fragment標籤所在的地方。

運行以後,效果以下:

實際上,這種方式在開發中並不推薦,咱們來介紹另一種方法。

 

4、在activity代碼中添加fragment:

【實例】點擊左側fragment中的按鈕,彈出右側的fragment。新建一個工程文件,而後步驟以下:

(1)將activity_main的佈局分爲兩部分:左邊佔1/4,右邊佔3/4。修改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"
    tools:context=".MainActivity"
    android:orientation="horizontal" >

    <LinearLayout
        android:id="@+id/left"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_weight="1"
        android:background="#00BFFF" >
        
        <Button 
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"            
            android:text="顯示"/>
        
    </LinearLayout>

    <LinearLayout
         android:id="@+id/right"       
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:background="#00FFFF"
        android:orientation="vertical" >

    </LinearLayout>

</LinearLayout>

上方代碼中,一個LinearLayout表明一個Fragment的容器,記得要給每一個fragment加一個容器的id。上方代碼的佈局效果以下:

既然兩個fragment的空間都分配好了,接下來右邊的Fragment寫出來。

(2)新建文件fragment_right.xml和RightFragment.java:

fragment_right.xml代碼以下:(添加一個文本和按鈕)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="新聞內容" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

RightFragment.java代碼以下:

package com.example.m01_fragment03;

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

public class RightFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_right, null);
        return view;
    }
    
    @Override
    public void onPause() {
        super.onPause();
    }
}

緊接着,咱們修改上方onCreateView()方法中的代碼,實現點擊按鈕,可以彈出吐司:

 1 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 2             Bundle savedInstanceState) {
 3         View view = inflater.inflate(R.layout.fragment_right, null);
 4         Button button = (Button)view.findViewById(R.id.button2);  5         button.setOnClickListener(new OnClickListener() {  6  @Override  7             public void onClick(View v) {  8                 Toast.makeText(getActivity(), "我是fragment", Toast.LENGTH_SHORT).show();  9             }
10         });
11         return view;
12     }

第04行代碼:有一個單詞view不要忘了。

第08行代碼:第一個參數必定是getActivity,以此來得到父類的Activity

(3)在activity代碼中添加fragment:

點擊MainActivity中左側的按鈕,彈出右側的Fragment,

MainActivity.java的監聽器部分的代碼以下:

 1         button.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5 
 6                 //步驟一:添加一個FragmentTransaction的實例
 7                 FragmentManager fragmentManager =getFragmentManager();  8                 FragmentTransaction transaction = fragmentManager.beginTransaction();  9 
10                 //步驟二:用add()方法加上Fragment的對象rightFragment 
11                 RightFragment rightFragment = new RightFragment(); 12  transaction.add(R.id.right, rightFragment); 13 
14                 //步驟三:調用commit()方法使得FragmentTransaction實例的改變生效
15  transaction.commit();          
16             }
17         });

記住上面的三個步驟。

第12行代碼是整個程序的核心。add()方法裏的第一個參數是容器視圖資源ID,而不是layout。容器視圖資源ID有兩個做用:

  • 告知FragmentManager,fragment視圖應該出如今activity視圖的什麼地方
  • 是FragmentManager隊列中fragment的惟一標識符

運行後,效果以下:

點擊左側的按鈕後,出現右側的界面。點擊右側的按鈕,彈出吐司。效果以下:

固然,這個代碼還不夠成熟,由於還涉及到了生命週期沒有處理。咱們將在下一章節中進行講解。

 

【索引】

若是你對本文存在疑惑,請參考本人關於Fragment的系列文章:(不斷更新)

Android系列之Fragment(一)----Fragment加載到Activity當中

Android系列之Fragment(二)----Fragment的生命週期和返回棧

Android系列之Fragment(三)----Fragment和Activity之間的通訊(含接口回調)

Android系列之Fragment(四)----ListFragment的使用

相關文章
相關標籤/搜索