Android是在Android 3.0 (API level 11)开始引入Fragment的。可以把Fragment当成Activity的一个界面的一个组成部分,甚至Activity的界面可以完全有不同的Fragment组成,而且Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个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的类似。
使用Support Library
Support Library是一个提供了API库函数的JAR文件,这样就可以在旧版本的Android上使用一些新版本的APIs。
比如android-support-v4.jar.它的完整路径是:
<sdk>/extras/android/support/v4/android-support-v4.jar.
它就提供了Fragment的APIs,使得在Android 1.6 (API level 4)以上的系统都可以使用Fragment。
为了确定没有在旧版本系统上使用新版本的APIs,需要如下导入语句:
import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager;
必须实现的回调函数
onCreateView()
当第一次绘制Fragment的UI时系统调用这个方法,必须返回一个View,如果Fragment不提供UI也可以返回null。
注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。
public class ExampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); } }
把Fragment加入Activity
Fragment有两种加载方式:一种是在Activity的layout中使用标签<fragment>声明;另一种方法是在代码中把它加入到一个指定的ViewGroup中。
加载方式1:通过Activity的布局文件将Fragment加入Activity
在Activity的布局文件中,将Fragment作为一个子标签加入即可。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /></LinearLayout>
加载方式2:通过编程的方式将Fragment加入到一个ViewGroup中
当Activity处于Running状态下的时候,可以在Activity的布局中动态地加入Fragment,只需要指定加入这个Fragment的父View Group即可。
首先,需要一个FragmentTransaction实例:
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();(注,如果importandroid.support.v4.app.FragmentManager;那么使用的是:FragmentManager fragmentManager = getSupportFragmentManager();)
之后,用add()方法加上Fragment的对象:
ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.fragment_container, fragment); fragmentTransaction.commit();其中第一个参数是这个fragment的容器,即父控件组。
最后需要调用commit()方法使得FragmentTransaction实例的改变生效。
1、新建工程
2.、创建若干个简单的布局(用于fragment的加载),如下:
activiy_main为主布局文件,fragment1,fragment2为fragment的布局文件
3、创建 Fragment 的类
创建Fragment1:创建过程与创建Activity类似,不过继承的是android.support.v4.app.Fragment
创建 Fragment2 :同上
复写onCreateView函数加载fragment的布局,R.layout.fragment1就是刚刚创建的布局文件。
4、运行
底栏按钮切换界面的实现(类似QQ底栏)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/bottom" android:layout_width="match_parent" android:layout_height="65dp" android:layout_alignParentBottom="true" android:background="@null" android:gravity="center_vertical" android:orientation="horizontal" > <Button android:id="@+id/f1" android:layout_width="0dp" android:layout_height="50dp" android:layout_weight="1" android:text="fragment1" /> <Button android:id="@+id/f2" android:layout_width="0dp" android:layout_height="50dp" android:layout_weight="1" android:text="fragment2" /> </LinearLayout> <FrameLayout <!-- 注意,这里是帧布局不是Fragment --!> android:id="@+id/content_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottom" android:background="#fff" > </FrameLayout> </RelativeLayout>
两个按钮组成的布局作为底栏,上面空白部分为帧布局:
public class Activity2 extends FragmentActivity {//注意!这里继承的是FragmentActivity private Button f1, f2; private Fragment mContent; //这里是Fragment而不是帧布局,帧布局不用声明 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2);//加载activity的布局 f1 = (Button) findViewById(R.id.f1);//实例化两个按钮 f2 = (Button) findViewById(R.id.f2); if (mContent == null) { mContent = new Fragment3(); //实例化Fragment //下面是重点! //Fragment通过FragmentManager来管理 //beginTransaction()返回Fragment事务管理实例 //replace()执行Fragment事务中的替换 //R.id.content_fragment用来装载Fragment的容器 //mContent用于替换的Fragment的对象 //commit()提交事务,完成操作 getSupportFragmentManager().beginTransaction().replace( R.id.content_fragment, mContent).commit(); } f1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mContent = new Fragment3(); if (mContent != null) { getSupportFragmentManager().beginTransaction() .replace(R.id.content_fragment, mContent).commit(); } } }); f2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mContent = new Fragment4(); if (mContent != null) { getSupportFragmentManager().beginTransaction() .replace(R.id.content_fragment, mContent).commit(); } } }); } }
市场上很多应用均采取的框架,从屏幕左侧划出菜单,点击菜 单,右侧界面进行相应的切换。
安卓5.0以前实现这种效果只能通过别人的开源代码实现,从5.0安卓开始提供了自带的侧滑菜单组件DrawerLayout,该组件在supportv4包下,兼容之前的版本。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 屏幕中的主內容 --> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- The navigation drawer --> <!-- 左滑菜单布局 --> <LinearLayout android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" 表示左边菜单 android:background="#ffffff" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/one" android:layout_width="240dp" android:layout_height="55dp" android:drawableLeft="@drawable/ic_launcher" android:gravity="center" android:text="第一个界面" android:textColor="#353535" android:textSize="23dp" /> <TextView android:id="@+id/two" android:layout_width="240dp" android:layout_height="55dp" android:drawableLeft="@drawable/ic_launcher" android:gravity="center" android:text="第二个界面" android:textColor="#353535" android:textSize="23dp" /> <TextView android:id="@+id/three" android:layout_width="240dp" android:layout_height="55dp" android:drawableLeft="@drawable/ic_launcher" android:gravity="center" android:text="第三个界面" android:textColor="#353535" android:textSize="23dp" /> </LinearLayout> <!-- 增加右边抽屉显示 --> <TextView android:id="@+id/right_drawer" android:layout_width="280dp" android:layout_height="match_parent" android:layout_gravity="end" 表示右边菜单 android:background="#ffffff" android:gravity="center" android:text="@string/right_drawer_info" android:textColor="#444444" android:textSize="30sp" > </TextView> </android.support.v4.widget.DrawerLayout> </LinearLayout>
public class MainActivity extends FragmentActivity {// 集成的是FragmentActivity private DrawerLayout mDrawerLayout;// 侧滑菜单 private LinearLayout mDrawerList;// 侧滑菜单的布局 private MenuListener menuListener;// 监听 private TextView one, two, three;// 侧滑菜单中的三个TextView @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 实例化操作 mDrawerList = (LinearLayout) findViewById(R.id.left_drawer); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); one = (TextView) findViewById(R.id.one); two = (TextView) findViewById(R.id.two); three = (TextView) findViewById(R.id.three); menuListener = new MenuListener(); one.setOnClickListener(menuListener); two.setOnClickListener(menuListener); three.setOnClickListener(menuListener); // 设置菜单被拉出时的阴影 mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // 默认显示第一个Fragment Fragment fragment = new Fragment1().getNewInstance(); FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment).commit(); } // 主要是三个TextView的监听事件 private class MenuListener implements View.OnClickListener { @Override public void onClick(View v) { // TODO Auto-generated method stub Fragment fragment = null; switch (v.getId()) { case R.id.one: fragment = new Fragment1().getNewInstance(); break; case R.id.two: fragment = new Fragment2(); break; case R.id.three: fragment = new Fragment3(); break; default: break; } FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment).commit(); // 点击后关闭侧滑菜单 mDrawerLayout.closeDrawer(mDrawerList); } } }