Fragment是Android在3.0版加入的一种全新的系统元素,因为在3.0版以后开始支持大屏幕的平板设备,这使得在平板设备上一次可以显示更多的内容元素,为了让一份代码可以同时在手机和平板上运行,Fragment应运而生。具体做法就是在一个布局下可以同时安置多个fragment,如果设备是小屏的手机,那系统会自动判断显示其中的几个fragment,另外的通过触发在下一屏显示;如果是大屏的平板设备,那就所有元素同时显示出来,就像这样:
这么做的确实为程序的编写带来了便利,但同时也增加了产品设计的难度,毕竟平板设备和手机的差别还是比较大的,手机屏在4寸左右,而平板集中在7-10寸,对于这么明显的差别一般的产品都会设计出不同的UI来优化体验,而不是简单的把平板作为手机屏幕的延展,让1+1=2。举个例子就像QQ针对不同的设备分别设计了手机QQ、QQHD、QQHDMini。
Fragment生命周期
上面两幅图显示了Fragment的生命周期及与Activity关系,基本流程是一样的,只是Fragment中多了一些方法,同时Fragment的生命周期与其对应的Activity相关联,下面是从官网翻译来的解释:
onAttach
当Fragment与Activity关联起来的时候被调用(Activity在这里被传进来);
onCreate
当Fragment创建时被系统调用,在这里应该初始化希望一直保持的必要组件;
onCreateView
当Fragment第一次绘制他的UI时系统调用此方法,为了绘制Fragment的UI,该方法必须返回该layout的根视图,当然如果这个Fragment不希望绘制视图可以返回null;
onActivityCreated
当Activity的onCreate()方法返回时会 调用此方法;
onStart
当Fragment可见的时候调用,与Activity的相同;
onResume
当Frament处于活跃状态时调用,与Activity相同;
onPause
当用户离开该Fragment时被系统调用,然而这并不意味着要被销毁,但是用户应该在此时提交任何要持久化的东西,因为用户可能不会再返回了;
onStop
在Activity的onStop方法后调用;
onDestroyView
当与该Fragment相关联的view树被移除时调用;
onDestroy
该Fragment不再使用是被调用;
onDetach
该Fragment与Activity解除关联时调用。
一般最少要覆写onCreate、onCreateView、onPause三个方法将就可以正常使用一个Fragment。
Fragment使用
使用Fragment需要继承Fragment类,实现上面的生命周期方法,也可以继承系统提供的特殊的Fragment,例如DialogFragment、ListFragment、PreferenceFragment等。
Fragment添加方式
1、在xml文件中添加,例如
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.android.fragments.HeadlinesFragment"
android:id="@+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
这种方式在系统加载Activity的时候通过setContentView(),会自动实例化相关的Fragment。但是这种方式需要注意的是在生成相应的Fragment后就不能再进行移除的操作,相应的视图会固化到该Layout里。如果想对Fragment进行动态加载管理,就需要 使用 下面的代码添加方式。
2、在代码中添加
1)需要FragmentManager来创建一个FragmentTranscation,来提供Fragment的添加、移除等操作;
2)用fragmentTransction对fragment进行操作后,需要使用commit()方法进行提交使操作生效。
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// 检查装载Fragment的容器是否存在
if (findViewById(R.id.fragment_container) != null) {
// 如果是从先前的状态恢复的就不需要再进行实例化了
if (savedInstanceState != null) {
return;
}
// Fragment实例化
HeadlinesFragment firstFragment = new HeadlinesFragment();
// 如果传入的Intent包含有fragment需要的信息,就把它传进去
firstFragment.setArguments(getIntent().getExtras());
// 把Fragment加到容器里,提交
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
getSupportFragmentManager() -> 获得一个FragmentManager;
beginTransaction() -> 获得一个FragmentTransaction;
add() -> 添加一个Fragment;
commit() -> 提交操作。
在add()的位置使用replace()可以执行替换的操作,这里如果希望用户可以获得回退的操作,那么就需要在commit()方法进行提交前使用addToBackStack()进行压栈操作,此时原有的Fragment将进入onStop状态而不会销毁,如果不进行压栈操作,那Fragment就会被销毁了。
可以添加多个Fragment到一个容器中,他们在容器中的显示顺序与添加顺序相同;可以在addToBackStack之前执行多个操作,例如add之后进行replace,但系统会把这些看做一个操作,回退时他们会一起进行。