一、什么是Fragment (是一种封装、重用的思想。)
中文名“碎片”
Fragment碎片或者是片段,是用户界面的一部分。你可以将其看成一个View,
他有自己的生命周期,接收自己的输入事件,你可以添加、删除、替换。
Fragment必须是依附于Activity之上。
什么时候要使用fragment,以及在Activity设计里面搞几个fragment,关键看“封装、重用”
二、作用
1.可以动态和灵活的使用UI;例如根据屏幕大小来选择加载不同的显示效果
2.可以重用(需要分装);
3.可以实现代码分离;
( fragment并不一定必须是activity布局的一部分;
也可以将一个fragment作为activity的隐藏的后台工作者.--不会调用onCreateView方法)
三、举例子
1)app里面很多时候需要登录才能进入的一些界面。这时候
如果用户没有登录,先显示的是登录界面。
如果用户已经登录,就显示的是下单界面or收藏界面等。
2)平板设计,平板和手机显示的UI布局不一样。
如何做到一个项目里面-同样的功能模块,在手机和平板里面显示的效果不一样?
(1)如何做到手机和平板使用不同的布局?
系统会自动处理。layout/layout-large
(布局1:menufragment, 布局2:menuAfragment,Detailfragment))
(2)写一个Activity,在MenuAfragment里面做判断--执行不同的处理。
注意:fragment必须要id或者tag;或者都不添加,但是它的父容器必须有要有id
判断是否是平板:
/**
* 判断当前设备是手机还是平板,代码来自 Google I/O App for Android
* @param context
* @return 平板返回 True,手机返回 False
*/
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp
四、使用
两种方式:
1.低版本(<3.0的版本)
1)导包android-support-v4.jar (在sdk的extra目录下面)
android.support.v4.app.Fragment
2) 写一个Fragment类 ---继承Fragment(android.support.v4.app.Fragment)
至少要重写onCreateView();----创建一个视图
3)将Fragment添加到布局里面
<fragment
android:name="myfragment的全类名"
//或者使用class="com.jky.fragment.MyFragment"
/>
4)将使用该布局的Activity继承FragmentActivity
-------------
2.高版本
1)写一个Fragment类 ---继承Fragment (android.app.Fragment)
至少要重写onCreateView();----创建一个视图
2)将Fragment添加到布局里面
<fragment
android:name="myfragment的全类名"
//或者使用class="com.jky.fragment.MyFragment"
/>
------------
3.动态添加
<FramLayout 帧布局
1)使用FragmentManager
2)事务tran = fm.beginTransaction();
tran.add()
tran.replace();
tran.remove();
tran.hide();
tran.show();
tran.commit();
4.平板设计
注:每个 fragment 都需要提供一个ID(也可以是tag),系统在 activity 重新创建时用它来恢复 fragment,
也可以用它来操作 fragment 进行其它的事物,比如删除它。
5.fragment的生命周期
1)
2) 注意事项:
fragment生命周期是由Activity控制的。
a.不要在onCreateView里面去操作Activity的元素(比如回调Activity方法来操作它的界面);
因为这时候Activity还没有创建好,应该在onActivityCreated里面做;
b.加事务回退栈,fragment被replace或者remove的时候不会被销毁(停在了onDestroyView),
当回来的时候fragment又会重新onCreateView.
因此这就需要我们在操作的时候注意,如果你replace或remove后加入回退栈,要注意保存数据。
那么如何保存数据呢?
方法1:由于不会destroy,所以可以保存到fragment的全局变量里面。
方法2:像EditText可以不用这么麻烦,只要给其添加ID,系统会自动还原里面的数据
方法3:既然fragment中的变量都会被保存,那我们直接将Fragment的视图直接保存到变量中,
在系统在利用onCreateView()创建视图的时候,我们直接返回保存的视图。
1、创建一个变量,保存Fragment的视图:
private View rootView;
` 2、然后来看onCreateView的实现
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return getPersistentView(inflater, container, savedInstanceState, R.layout.fragment1);
}
public View getPersistentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layout) {
if (rootView == null) {
// Inflate the layout for this fragment
rootView = inflater.inflate(layout, container,false);
} else {
((ViewGroup) rootView.getParent()).removeView(rootView);
}
return rootView;
}
注意:onCreateView()中返回的视图是要添加到ViewTree中去的。
而这里的rootView视图在上次已经添加到里面去了,
一个视图实例不能被add两次,不然就会被下面这个错误!
所以,我们针对这种情况,如果rootView已经存在于ViewTree中的时候,要先从ViewTree中移除。
c.hide和多个add方法,不会对当前fragment生命周期造成影响。
如何当一个fragment不在前台显示的时候 怎么处理资源释放等问题?
在commit后自己来调用fragment里面的方法手动适当处理一些资源问题。
3)如何保存数据?
6.回退栈
FragmentTransaction ft = fm.beginTransaction();
AFragment f = new AFragment();
ft.add(R.id.fl, f,"afragment");
ft.addToBackStack("stack1");
ft.commit();
fm.popBackStack();相当于返回键
fragment注意事项
1)不要在onCreateView里面去操作Activity的元素(比如回调Activity方法来操作它的界面);
因为这时候Activity还没有创建好,应该在onActivityCreated里面做;
2)没有加回退栈之前我们使用replace方法去替换fragment的时候,那么之前的fragment会被杀死,生命周期执行完。———-当我们添加回退栈的时候我们使用replace方法替换之前的fragment,那么之前的fragment不会被杀死,这个时候只会调用(onPause ——> onStop—>onDestoryView),但是之前被替换了的fragment身上的view会被干掉
3)当我们使用add fragment的时候,我们不添加回退栈,这个时候我们的fragment没有显示在前台的时候,这个时候framgent的生命周期方法是不会改变的。添加回退栈同上。当我们点击返回键的时候,fragment才会被销毁掉。
4)我们的调用show fragment和hide fragment我们的生命周期方法都是不会发生改变。
5)remove fragment的时候我们的生命周期方法也会发生改变
6)当我们启动新的activity的时候,我们的fragment的生命周期也会发生改变(为什么?因为我们的activity的生命周期发生了改变,所以我们的fragment的生命周期也随之发生变化)
7)解决fragment里面我们的view被销毁问题?(调用了onDestoryView)
如果你replace或remove后加入回退栈,要注意保存数据。
那么如何保存数据呢?
7.1)保存控件
7.2)保存rootview
7.3)保存数据(因为有时候我们的数据他是一个model)
7.4)设置id
整理自教程