android:碎片的使用方式

yufan發表於2016-01-27

介紹了這麼多抽象的東西,也是時候應該學習一下碎片的具體用法了。你已經知道,碎 片通常都是在平板開發中才會使用的,因此我們首先要做的就是新建一個平板電腦的模擬 器。由於 4.0 系統的平板模擬器好像存在 bug,這裡我就新建一個 4.2 系統的平板模擬器,如 圖 4.4 所示。

 

 

 

 

 

圖   4.4

 

現在啟動這個平板模擬器,效果如圖 4.5 所示。

 

 

 

圖   4.5

 

 

 

好了,準備工作都完成了,接著新建一個 FragmentTest 專案,然後開始我們的碎片探索

之旅吧。

 

4.2.1    碎片的簡單用法

 

這裡我們準備先寫一個最簡單的碎片示例來練練手,在一個活動當中新增兩個碎片,並 讓這兩個碎片平分活動空間。

新建一個左側碎片佈局 left_fragment.xml,程式碼如下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"

android:orientation="vertical" >

 

 

<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Button"

/>

 

 

</LinearLayout>

這個佈局非常簡單,只放置了一個按鈕,並讓它水平居中顯示。然後新建右側碎片佈局

right_fragment.xml,程式碼如下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"

android:background="#00ff00" android:orientation="vertical" >

 

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp"

android:text="This is right fragment"

/>

 

 

</LinearLayout>

 

 

 

可以看到,我們將這個佈局的背景色設定成綠色,並放置了一個 TextView 用於顯示一

段文字。接著新建一個 LeftFragment 類,繼承自 Fragment。注意,這裡可能會有兩個不同包 下的 Fragment 供你選擇,建議使用 android.app.Fragment,因為我們的程式是面向 Android 4.0 以上系統的,另一個包下的 Fragment 主要是用於相容低版本的 Android 系統。LeftFragment 的程式碼如下所示:

 

public class LeftFragment extends Fragment {

 

 

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

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

return view;

}

 

 

}

這裡僅僅是重寫了 Fragment 的 onCreateView()方法,然後在這個方法中通過 LayoutInflater 的 inflate()方法將剛才定義的 left_fragment 佈局動態載入進來,整個方法簡單明瞭。接著我 們用同樣的方法再新建一個 RightFragment,程式碼如下所示:

 

public class RightFragment extends Fragment {

 

 

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

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

return view;

}

 

 

}

基本上程式碼都是相同的,相信已經沒有必要再做什麼解釋了。接下來修改 activity_main.xml

中的程式碼,如下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >

 

<fragment android:id="@+id/left_fragment"

 

 

 

android:name="com.example.fragmenttest.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" />

 

<fragment android:id="@+id/right_fragment" android:name="com.example.fragmenttest.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" />

 

</LinearLayout>

可以看到,我們使用了<fragment>標籤在佈局中新增碎片,其中指定的大多數屬性你都 是熟悉的,只不過這裡還需要通過 android:name 屬性來顯式指明要新增的碎片類名,注意一 定要將類的包名也加上。

這樣最簡單的碎片示例就已經寫好了,現在執行一下程式,效果如圖 4.6 所示。

 

 

 

圖   4.6

 

正如我們所期待的一樣,兩個碎片平分了整個活動的佈局。不過這個例子實在是太簡單 了,在真正的專案中很難有什麼實際的作用,因此我們馬上來看一看,關於碎片更加高階的 使用技巧。

 

 

 

4.2.2    動態新增碎片

 

在上一節當中,你已經學會了在佈局檔案中新增碎片的方法,不過碎片真正的強大之處 在於,它可以在程式執行時動態地新增到活動當中。根據具體情況來動態地新增碎片,你就 可以將程式介面定製得更加多樣化。

我們還是在上一節程式碼的基礎上繼續完善,新建 another_right_fragment.xml,程式碼如下 所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"

android:background="#ffff00" android:orientation="vertical" >

 

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp"

android:text="This is another right fragment"

/>

 

 

</LinearLayout>

這個佈局檔案的程式碼和 right_fragment.xml 中的程式碼基本相同,只是將背景色改成了黃 色,並將顯示的文字改了改。然後新建 AnotherRightFragment 作為另一個右側碎片,程式碼如 下所示:

 

public class AnotherRightFragment extends Fragment {

 

 

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.another_right_fragment,

container, false);

return view;

}

 

 

}

程式碼同樣非常簡單,在 onCreateView()方法中載入了剛剛建立的 another_right_fragment

 

 

 

佈局。這樣我們就準備好了另一個碎片,接下來看一下如何將它動態地新增到活動當中。修

改 activity_main.xml,程式碼如下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">

 

<fragment android:id="@+id/left_fragment" android:name="com.example.fragmenttest.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" />

 

<FrameLayout android:id="@+id/right_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" >

 

<fragment android:id="@+id/right_fragment" android:name="com.example.fragmenttest.RightFragment" android:layout_width="match_parent" android:layout_height="match_parent" />

 

</FrameLayout>

 

 

</LinearLayout>

可以看到,現在將右側碎片放在了一個 FrameLayout 中,還記得這個佈局嗎?在上一章 中我們學過,這是 Android 中最簡單的一種佈局,它沒有任何的定位方式,所有的控制元件都會 擺放在佈局的左上角。由於這裡僅需要在佈局裡放入一個碎片,因此非常適合使用 FrameLayout。

之後我們將在程式碼中替換 FrameLayout 裡的內容,從而實現動態新增碎片的功能。修改

MainActivity 中的程式碼,如下所示:

 

public class MainActivity extends Activity implements OnClickListener {

 

 

@Override

 

 

 

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

Button button = (Button) findViewById(R.id.button);

button.setOnClickListener(this);

}

 

 

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.button:

AnotherRightFragment fragment = new AnotherRightFragment(); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.

beginTransaction();

transaction.replace(R.id.right_layout, fragment);

transaction.commit();

break;

default:

break;

}

}

 

}

可以看到,首先我們給左側碎片中的按鈕註冊了一個點選事件,然後將動態新增碎片的 邏輯都放在了點選事件裡進行。結合程式碼可以看出,動態新增碎片主要分為 5 步。

1.    建立待新增的碎片例項。

2.    獲取到 FragmentManager,在活動中可以直接呼叫 getFragmentManager()方法得到。

3.    開啟一個事務,通過呼叫 beginTransaction()方法開啟。

4.    向容器內加入碎片,一般使用 replace()方法實現,需要傳入容器的 id 和待新增的碎 片例項。

5.    提交事務,呼叫 commit()方法來完成。 這樣就完成了在活動中動態新增碎片的功能,重新執行程式,可以看到和之前相同的界

面,然後點選一下按鈕,效果如圖 4.7 所示。

 

 

 

 

 

圖   4.7

 

 

4.2.3    在碎片中模擬返回棧

 

在上一小節中,我們成功實現了向活動中動態新增碎片的功能,不過你嘗試一下就會發 現,通過點選按鈕新增了一個碎片之後,這時按下 Back 鍵程式就會直接退出。如果這裡我 們想模仿類似於返回棧的效果,按下 Back 鍵可以回到上一個碎片,該如何實現呢?

其實很簡單,FragmentTransaction 中提供了一個 addToBackStack()方法,可以用於將一 個事務新增到返回棧中,修改 MainActivity 中的程式碼,如下所示:

 

public class MainActivity extends Activity implements OnClickListener {

……

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.button:

AnotherRightFragment fragment = new AnotherRightFragment(); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.

beginTransaction();

transaction.replace(R.id.right_layout, fragment); transaction.addToBackStack(null); transaction.commit();

 

 

 

break;

default:

break;

}

}

}

這裡我們在事務提交之前呼叫了 FragmentTransaction 的 addToBackStack()方法,它可以 接收一個名字用於描述返回棧的狀態,一般傳入 null 即可。現在重新執行程式,並點選按鈕 將 AnotherRightFragment 新增到活動中,然後按下 Back 鍵,你會發現程式並沒有退出,而 是回到了 RightFragment 介面,再次按下 Back 鍵程式才會退出。

 

4.2.4    碎片和活動之間進行通訊

 

雖然碎片都是嵌入在活動中顯示的,可是實際上它們的關係並沒有那麼親密。你可以看 出,碎片和活動都是各自存在於一個獨立的類當中的,它們之間並沒有那麼明顯的方式來直 接進行通訊。如果想要在活動中呼叫碎片裡的方法,或者在碎片中呼叫活動裡的方法,應該 如何實現呢?

為了方便碎片和活動之間進行通訊,FragmentManager 提供了一個類似於 findViewById()

的方法,專門用於從佈局檔案中獲取碎片的例項,程式碼如下所示:

 

RightFragment rightFragment = (RightFragment) getFragmentManager()

.findFragmentById(R.id.right_fragment);

呼叫 FragmentManager 的 findFragmentById()方法,可以在活動中得到相應碎片的例項, 然後就能輕鬆地呼叫碎片裡的方法了。

掌握瞭如何在活動中呼叫碎片裡的方法,那在碎片中又該怎樣呼叫活動裡的方法呢?其 實這就更簡單了,在每個碎片中都可以通過呼叫 getActivity()方法來得到和當前碎片相關聯 的活動例項,程式碼如下所示:

 

MainActivity activity = (MainActivity) getActivity();

有了活動例項之後,在碎片中呼叫活動裡的方法就變得輕而易舉了。另外當碎片中需要 使用 Context 物件時,也可以使用 getActivity()方法,因為獲取到的活動本身就是一個 Context 物件了。

這時不知道你心中會不會產生一個疑問,既然碎片和活動之間的通訊問題已經解決了, 那麼碎片和碎片之間可不可以進行通訊呢?

說實在的,這個問題並沒有看上去的複雜,它的基本思路非常簡單,首先在一個碎片中 可以得到與它相關聯的活動,然後再通過這個活動去獲取另外一個碎片的例項,這樣也就實 現了不同碎片之間的通訊功能,因此這裡我們的答案是肯定的。

相關文章