Fragment的使用
1 Fragment的生命周期
Fragment是依附于Activity而存在的,故而Activity的额生命周期直接影响到Fragment的生命周期。先来看下官网给的生命周期图。
从上面可以看出,Fragment多了以下几个主要方法:
- onAttach(Activity):当Fragment与Activity发生关联时调用。
- onCreateView(LayoutInflater, ViewGroup,Bundle):创建该Fragment的视图。
- onActivityCreated(Bundle):当Activity的onCreate方法返回时调用。
- onDestoryView():与onCreateView想对应,当该Fragment的视图被移除时调用。
- onDetach():与onAttach相对应,当Fragment与Activity关联被取消时调用。
2 Fragment的使用
1 静态添加
- 继承Fragment,重写onCreateView,决定Fragemnt的布局;
- 在Activity中声明此Fragment,就当和普通的View一样。使用< fragment>标签添加碎片,android:name属性来显式指明要添加的碎片类名,注意一定要将类的包名也加上。
2 动态添加
- 创建待添加的碎片实例。
- 获取到FragmentManager,在活动中可以直接调用 getFragmentManager()方法得到。(app包下的fragment,v4包的则使用getSupportFragmentManager,用于支持兼容低版本)
- 开启一个事务,通过调用 beginTransaction()方法开启。
- 向容器内加入碎片,一般使用 replace()方法实现,需要传入容器的 id 和待添加的碎片实例。
- 提交事务,调用 commit()方法来完成。
3 注意点
如果使用Android3.0以下的版本,需要引入v4的包,然后Activity继承FragmentActivity,然后通过 getSupportFragmentManager获得FragmentManager。不过还是建议版Menifest文件的uses-sdk的 minSdkVersion和targetSdkVersion都改为11以上,这样就不必引入v4包了。
3 主要API方法
1 FragmentManage
主要用于在Activity中操作Fragment,获取的方式为:
//app包 getFragmentManager() // v4包中,getSupportFragmentManager
2 FragmentTransaction
保证一些列Fragment操作的原子性,Fragment的事务处理,获取的方式为:
//开启一个事务FragmentTransaction transaction = fm.benginTransatcion();
常用方法有:
//添加transaction.add()//删除。如果没添加到回退栈,则fragment实例销毁transaction.remove()//替换,相当于remove+addtransaction.replace()//隐藏当前的Fragment,仅仅是设为不可见,并不会销毁transaction.hide()//显示之前隐藏的Fragmenttransaction.show()//提交本次事务。一定要在Activity.onSaveInstance()之前调用transatcion.commit()
4 Fragment与Activity的通信
1 获取Fragment实例
Fragment实例的获取因Fragment添加方式不同而不同。
1 静态添加的Fragment
在activity的布局中的< fragment>标签内设置android:id属性,调用 FragmentManager 的 findFragmentById()方法+强转获取到Fragment的实例对象。
2 动态添加的Fragment
一种是直接实例化Fragment对象,用实例对象进行后续的操作。
另一种是在add或者replace 的时候添加第三个TAG参数,然后通过调用 FragmentManager 的findFragmentByTag()方法+强转获取Fragment实例对象。此时如果如果需要获取控件上的信息,可以通过 实例.getActivity().findViewById()的形式获取到相关的控件。
2 获取Activity实例
在Fragment中可以通过getActivity()得到当前绑定的Activity的实例,然后进行操作。
需要注意的是,如果在Fragment中需要Context,可以通过调用getActivity() ,如果该Context需要在Activity 被销毁后还存在,则使用 getActivity().getApplicationContext()。
5 进阶
1 回退栈的管理
Fragment不像activity一样自带一个任务栈进行管理,它需要人为的进行添加:
FragmentTransaction.addToBackStack(null);
2 屏幕选择避免重新创建Fragment
1 产生原因
因为当屏幕发生旋转,Activity发生重新启动,默认的Activity中的Fragment也会跟着Activity重新创建;这样造成当旋转的时候,本身存在的Fragment会重新启动,然后当执行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现该问题的原因。
2 解决方法
通过检查onCreate的参数
Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建。
代码如下:
//在setContentView后面添加if (savedInstanceState == null){ mFOne=new FragmentOne(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, mFOne, "ONE"); tx.commit(); }
上述仅仅只是解决了界面的重绘,那数据又该如何处理呢?
我们知道,在activity中有onSaveInstanceState()可以进行保存数据,Fragment也同样有此方法。
而activity可以在Created中进行数据的恢复,通过前面的生命周期图可以看出,Fragment在onCreate 或者onCreateView 或者onActivityCreated进行恢复都可以进行数据的恢复。
3 单双页自动选择
1 问题的产生
一个APP需要应对不用屏幕大小的设备,在平板上,有时候会包含2个碎片,即双页,而手机屏幕小只有一个碎片,那么如何让APP自动识别呢?
2 解决的方案
在《第一行代码》中,郭神给出了解决的方法:
新建一个layout_large包,并新建双页显示的布局文件(文件名和单页显示的一致)
其中 large 就是一个限定符,那些屏幕被认
为是 large 的设备就会自动加载 layout-large 文件夹下的布局,而小屏幕的设备则还是会加载layout 文件夹下的布局。
下面是Android 中一些常见的限定符参考表。
可是large到底是多large呢?为了更加灵活地为各种设备加载不同的布局,此时就需要最小宽度限定符( Smallest-width Qualifier)。
最小宽度限定符允许我们对屏幕的宽度指定一个最小指(以dp为单位),然后以这个最
小值为临界点,屏幕宽度大于这个值的设备就加载一个布局,屏幕宽度小于这个值的设备就
加载另一个布局。
例如在 res 目录下新建layout-sw600dp文件夹,这样屏幕宽度大于 600dp 的设备上时,会加载 layout-sw600dp中的布局;当程序运行在屏幕宽度小于 600dp 的设备上时,则仍然加载默认的layout中的布局。
需要注意一点,最小宽度限定符是在 Android 3.2 版本引入的,由于这里我们最低兼容
的系统版本是 4.0,所以可以放心地使用它。
4 Fragment与ActionBar和MenuItem集成
Fragment中:
a、在Fragment的onCreate中调用 setHasOptionsMenu(true);
@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true);//步骤1}
b、然后在Fragment子类中实现onCreateOptionsMenu
@Overridepublic void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.fragment,menu);// super.onCreateOptionsMenu(menu, inflater);}
c、如果希望在Fragment中处理MenuItem的点击,也可以实现onOptionsItemSelected;当然了Activity也可以直接处理该MenuItem的点击事件。
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { if(R.id.settings==item.getItemId()){//步骤3,改return true Toast.makeText(getActivity(), "测试", Toast.LENGTH_SHORT).show(); } return true;}
Activity中:
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: { Toast.makeText(this, "主页面", Toast.LENGTH_SHORT).show(); return true; } default: //如果希望Fragment自己处理MenuItem点击事件,一定不要忘了调用super.xxx return super.onOptionsItemSelected(item); }}
效果图如下所示:
5 没有布局的Fragment的作用
没有布局文件Fragment实际上是为了保存,当Activity重启时,保存大量数据准备的。
更多相关文章
- Android(安卓)监听软键盘状态的实例详解
- 基于AndroidStudio开发的简单登陆页面制作
- Android学习笔记(三)UI
- Android(安卓)RelativeLayout布局
- AndroidStudio常见问题
- AndroidStudio插件:布局文件转化Databinding
- Android(安卓)SlidingMenu 布局实现
- 【Android】毫无耦合性,一个Item根布局搞定 item侧滑删除菜单,像IO
- flutter的AndroidX版本适配