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。