在Android(安卓)中Fragment 中嵌套使用Fragment 中使用
1. 前言
这几天接到一个坑的任务,领导要我做一个Android 蓝牙APK,要求是在平板上使用并且横屏分页显示,一边显示蓝牙广播搜索的设备,另一边存放指定已过滤的设备。
在Android中横屏显示,并且分页,自然而然就想到了Fragment,于是抽空学习一下Fragment的用法,并且在使用过程中遇到findFragmentById 返回为null。
今天遇到这个问题,真是头疼死了,找了很多资料都说是这样子使用,在原本可以运行的项目中的findFragmentByid返回值为null,原本可以运行的项目,竟然运行报错。
因此才有这一篇文章。
2. 基本概念
Fragment,又称碎片,也可以说是Activity的一个片段,是Android 3.0(API 11)提出的,为了兼容低版本,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6。
- Fragment是依赖于Activity的,不能独立存在的。
- 一个Activity里可以有多个Fragment。
- 一个Fragment可以被多个Activity重用。
- Fragment有自己的生命周期,并能接收输入事件。
- 我们能在Activity运行时动态地添加或删除Fragment。
Fragment的优势有以下几点:
- 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
- 可重用(Reusability):多个Activity可以重用一个Fragment。
- 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。
3. Fragment生命周期(参考菜鸟教程《Fragment基本概述》)
4. Fragment 使用(参考菜鸟教程《Fragment基本概述》)
Fragment 使用有两种方式,分为静态加载Fragment 和 动态加载Fragment
4.1 静态加载Fragment
对于静态加载需要注意的是:
4.1.1. 通过xml的方式添加,缺点是一旦添加就不能在运行时删除
4.1.2 自定义一个Fragment类,需要继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:Inflater.inflate()方法加载Fragment的布局XML文件,接着返回加载的view对象,在Inflater.inflat方法中的第三个参数必须为false,因为它还要停靠在容器中。
第三个参数是false,因为在Fragment内部实现中,会把该布局添加到container中,如果设为true,那么就会重复做两次添加,则会抛如下异常:
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call
4.1.3 在需要加载Fragment的Activity或者父Fragment(Fragment 包含Fragment) 对应的布局文件中添加fragment的标签, 记住,name属性是全限定类名哦,就是要包含Fragment的包名,如下:
public abstract class BaseFragment extends Fragment{ protected View mRootView; protected Activity mActivity; @Override public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); mActivity = getActivity(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return initView(); }; //当fragment 依赖的activity onCreate方法结束时使用 @Override public void onActivityCreated(Bundle saveInstanceState) { super.onActivityCreated(saveInstanceState); initData(); } //子类必须初始化 public abstract View initView(); //子类初始化数据 public abstract void initData();}
4.2 动态加载Fragment(参考菜鸟教程《Fragment基本概述》)
4.2.1 在动态添加方式中,首先需要Activity 或者 父Fragment 中有一个
一个容器存放Fragment,一般是FrameLayout,因此在Activity的布局文件中加入FrameLayout:
在onCreate()
中,通过以下代码将Fragment添加进Activity中
if (bundle == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, Fragment1.newInstance("hello world"), "f1") .commit();}
使用动态方式,add()方法的第三个参数是fragment的tag名,指定tag的好处是后续我们可以通过Fragment1 frag = getSupportFragmentManager().findFragmentByTag("f1")
从FragmentManager中查找Fragment对象。
5. Fragment与Activity的交互(参考菜鸟教程《Fragment基本概述》)
5.1Fragment向Activity传递数据
在Fragment中定义接口,并让Activity实现该接口。
5.2 Activity向Fragment传递数据
Activity向Fragment传递数据比较简单,获取Fragment对象,并调用Fragment的方法即可,比如要将一个字符串传递给Fragmen
5.3Fragment之间通信
由于Fragment之间是没有任何依赖关系的,因此如果要进行Fragment之间的通信,建议通过Activity作为中介,不要Fragment之间直接通信,如下:
6. 在Fragment 中获取控件的方法,
mRootView = UIUtils.inflate(R.layout.fragment_home_left_layout); mRefreshLayout = (SwipeRefreshLayout) mRootView.findViewById(R.id.refreshLayout); mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { scanLeDevice(true); } }); listView = (MyListView) mRootView.findViewById(R.id.listView1);
7. Activity中获取Fragment组件的方法
首先getFragmentManager 、getSupportFragmentManager这个两个FragmentManager用的最多,Fragment是安卓3.0以后引入的API,FragmentManager是管理Fragment的片段管理器,直接使用,再
Fragment获得Activity中的组件: getActivity().findViewById(R.id.list);
Activity获得Fragment中的组件(根据id和tag都可以):getFragmentManager.findFragmentByid(R.id.fragment1);
8. Fragment 嵌套使用时,获取组件方法
当Fragment嵌套Fragment时(也就是说你的Fragment里面还有子Fragment),里面需要用getChildFragmentManager来获得FragmentManager,再使用findViewById(R.id.list), 或者findFragmentByid(R.id.fragment1);
关于Fragment 一些基本的认识就这些了,学习还要继续,付出总有回报的。
参考:
《Android Fragment 非常详细的一篇》
Fragment嵌套Fragment中getChildFragmentManager的问题
对于Fragment的一些理解
更多相关文章
- Android接口回调,最简单的理解方式
- Android(安卓)M 动态权限获取
- Android下的Service的基本用法
- Android版本兼容器
- 游走Android系列之Service
- Android中 Intent/Bundle传递对象取值为null的剖析以及Serializa
- Android第三方应用集成到Android系统的解决方法
- android AIDL RPC 机制
- android Handler的使用(二)