Fragment是Android 3.0 (API level 11)後推出的新功能。Android3.0以前的版本也能用Fragment,不過得給工程導入一個android-support-v4.jar的包。Fragment是一個有點類似Activity的東西,因爲針對安卓平板的相繼推出,屏幕越來越大,在一個這麼大的屏幕放一個Activity顯得佈局太大。因此你可以改成放兩個或多個Fragment,這些fragment都放在一個FragmentActivity裏。比如安卓官方文檔裏的Fragment使用案例就是屏幕左邊放一個Fragment顯示一個列表,列表裏都是一項一項的文章名稱,然後屏幕右邊放一個Fragment根據左邊Fragment選中的文章名稱將文章內容顯示在屏幕右邊的Fragment。每個Fragment裏面可以有自己的佈局文件,自己做佈局,操作起來有點類似Activity。
我這裏介紹一個自己寫的小例子,比較簡單,大家應該看得懂。
先來看下主佈局文件,主佈局文件中底部四個TextView用來點擊,點擊它們分別會將屏幕上的Fragment(這個Fragment就相當於上面的LinearLayout)進行替換和刪除(具體實現代碼待會介紹)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<LinearLayout
android:id="@+id/fragmentTop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="FragmentA"
android:background="#0000FF"
/>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="FragmentB"
android:background="#00FF00"
/>
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="FragmentC"
android:background="#FF0000"
/>
<TextView
android:id="@+id/text4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="刪除Fragment"
/>
</LinearLayout>
</RelativeLayout>
然後看看MainActivity,需要注意的地方在代碼裏都有解釋下。
package com.jackchan.fragmenttest;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.Fragment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text1 = (TextView)findViewById(R.id.text1);
TextView text2 = (TextView)findViewById(R.id.text2);
TextView text3 = (TextView)findViewById(R.id.text3);
TextView text4 = (TextView)findViewById(R.id.text4);
OnItemClickListener onClickListener = new OnItemClickListener();
text1.setOnClickListener(onClickListener);
text2.setOnClickListener(onClickListener);
text3.setOnClickListener(onClickListener);
text4.setOnClickListener(onClickListener);
showDetail(0);
}
/**
* 每次要操作commit方法時都要自己重新定義個FragmentMangager及FragmentTransaction,
* 千萬不要用統一的全局變量,那樣運行會報錯,我就遇到報commit already ...的錯誤。
*/
private void showDetail(int index){
//有些同學可能用的是3.0以前的版本,導入android-support-v4的包,因此下面的getFragmentManager()
//方法改爲getSuppotrFragmentManager(),這個方法纔是android-support-v4提供的
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment details = (Fragment)
getFragmentManager().findFragmentById(R.id.fragmentTop);
switch(index){
case 0:
details = new FragmentInit();
transaction.add(R.id.fragmentTop, details);//初始化的時候增加第一個Fragment
break;
case 1:
details = new FragmentA();
transaction.replace(R.id.fragmentTop, details);//替換Fragment
break;
case 2:
details = new FragmentB();
transaction.replace(R.id.fragmentTop, details);//替換Fragment
break;
case 3:
details = new FragmentC();
transaction.replace(R.id.fragmentTop, details);//替換Fragment
break;
case 4:
Toast.makeText(this, details.toString(), 3000).show();
transaction.remove(details);//刪除Fragment
break;
}
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
//addToBackStack()這個方法可以保證在comit一個操作後,在按返回鍵後能夠返回commit之前的效果
transaction.addToBackStack(null);
transaction.commit();
}
class OnItemClickListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId() == R.id.text1){
showDetail(1);
}
else if(v.getId() == R.id.text2){
showDetail(2);
}
else if(v.getId() == R.id.text3){
showDetail(3);
}
else if(v.getId() == R.id.text4){
showDetail(4);
}
}
}
}
剩下的就是四個Fragment和他們的佈局了。其實都是一樣的,我就只貼出FragmentInit和它對應的佈局文件fragment_init.xml
package com.jackchan.fragmenttest;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentInit extends Fragment{
@Override
/**
* 這個方法在生成該Fragment會被調用,生成該Fragment的佈局,有了佈局,大家就
* 可以像操作Activity那樣操作Fragment了。
*/
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//container是Fragment依附的框架,有時候由於程序跳轉等原因,可能Fragment還存在,但
//它依附的框架已經被回收,這個時候該Fragment其實沒有生成的必要了,因此直接return null
if(container == null){
return null;
}
View view = inflater.inflate(R.layout.fragment_init, container, false);
return view;
}
}
<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"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="初始Fragment"
/>
</LinearLayout>
FragmentA,FragmentB,FragmentC我寫得差不多,差別在每個佈局文件裏的TextView的文字分別爲這個是FragmentA,這個是FragmentB,這個是FragmentC。