Android片段_Fragment的最详细讲解
Android 在 Android 3.0(API 级别 11)中引入了片段,主要是为了给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。由于平板电脑的屏幕比手机屏幕大得多,通过将 Activity 布局分成片段,您可以在运行时修改 Activity 的部分外观,并在由 Activity 管理的返回栈中保留这些更改。
创建Fragment
完整的Fragment包含两部分:
- Fragment对象
- 布局
继承Fragment. fragment还支持V4兼容包用于兼容Android3.0之前的系统, 不过现在完全不需要去兼容4.0以下的Android系统了. 所以建议使用正常包.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class FragmentA extends Fragment { /** * 此方法是必须实现的方法, 否则此Fragment添加到Activity会Crash, 因为没有显示内容. * * @param inflater 内部提供的用于创建View对象的Inflater * @param container 父控件 * @param savedInstanceState 用于恢复数据 * @return 需要返回一个布局的View对象作为显示内容 */ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragement_a, null);  } } | 
普通的布局
| 1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="fragmentA" /> </LinearLayout> | 
Fragment是需要依附于Activity的”小Activity”, 所以需要添加到Activity中才能在界面显示. 支持两种方式添加, 其实原理都是一样.
动态添加
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 得到Fragment管理器 FragmentManager fragmentManager = getFragmentManager(); // 开启Fragment事务 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // 替换布局中的容器控件为Fragment的内容 fragmentTransaction.replace(R.id.activity_main, new FragmentA()); // 提交事务 fragmentTransaction.commit(); } } | 
<fragment>标签
通过直接在Activity中的布局添加标签的方式
这时可以看到右侧布局预览窗口提示
这是提示你没用设置该fragment具体显示内容. 因为你没用指定该fragment标签是显示什么内容, 可以点击提示输入.
| 1 2 3 4 5 | <fragment android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.liangjingkanji.fragment.FragmentA" tools:layout="@layout/fragement_a"/> | 
默认显示内容是FragmentA的内容, layout属性只是预览效果, 加与不加不影响实际效果.
关键类
Fragment
得到依附Activity实例
| 1 | Activity getActivity () | 
转场动画
这是为了支持Android5.0引入的Material Design过渡动画效果而添加的方法
| 1 2 | boolean getAllowEnterTransitionOverlap () boolean getAllowReturnTransitionOverlap () | 
得到转场动画
| 1 2 3 | Transition getEnterTransition () Transition getExitTransition () Transition getReturnTransition () | 
设置转场动画
| 1 2 3 | void setEnterTransition (Transition transition) void setExitTransition (Transition transition) void setReturnTransition (Transition transition) | 
Fragment的嵌套
得到FragmentManager
Fragment支持嵌套使用, 而该方法能得到Fragment内部的Fragment的管理器
| 1 | FragmentManager getChildFragmentManager () | 
该方法是得到把自己加到Activity里面的那个FragmentManager
| 1 | FragmentManager getFragmentManager () | 
得到父Fragment
| 1 | Fragment getParentFragment () | 
Fragment的子类
Fragment的直接和间接的子类有几十个. 我后面慢慢补充吧. 其实大概用法和内容都差不太多.
DialogFragment
看我的一篇专门介绍Android的对话框文字.
FragmentManager
开启事务
Fragment是需要FragmentTransaction事务创建
| 1 | FragmentTransaction beginTransaction () | 
得到Fragment
通过tag标签得到当前Activity显示的Fragment对象
| 1 | Fragment findFragmentByTag (String tag) | 
通过id找到Fragment
| 1 | Fragment findFragmentById (int id) | 
返回栈
得到当前返回栈的Fragment数量
| 1 | int getBackStackEntryCount () | 
弹出返回栈, 相当于模拟按下返回键
| 1 | void popBackStack () | 
监听返回栈的改变
| 1 | void addOnBackStackChangedListener (FragmentManager.OnBackStackChangedListener listener) | 
用完以后记得删除返回栈的监听器
| 1 | void removeOnBackStackChangedListener (FragmentManager.OnBackStackChangedListener listener) | 
FragmentTransaction
负责Fragment的事务管理的类
添加Fragment
可以添加多个Fragment插入到Activity的容器中, 多个Fragment处于重叠状态按照添加顺序显示视图, 前两个方法实际都是调用的第三个方法.
| 1 2 3 4 5 6 7 8 9 | FragmentTransaction add (Fragment fragment, // 该方法没有容器id相当于默认0, 所以并不会显示到界面 String tag) FragmentTransaction add (int containerViewId,  Fragment fragment) FragmentTransaction add (int containerViewId, // 被替换的容器ID Fragment fragment, // 需要替换的Fragment String tag) // 用于得到Fragment的tag | 
替换容器
容器即Avtivity上的布局控件, 必须是ViewGroup的子类.
添加和替换Fragment的区别: 在于替换会先删除原有的再添加. 而添加可以重复添加不会删除.
| 1 2 3 4 5 6 | FragmentTransaction replace (int containerViewId, // 容器ID Fragment fragment) FragmentTransaction replace (int containerViewId,  Fragment fragment, String tag) // 这个上面说过就不复述了 | 
隐藏和显示Fragment
隐藏已经存在Activity上的Fragment
| 1 | FragmentTransaction hide (Fragment fragment) | 
显示之前隐藏的Fragment
| 1 | FragmentTransaction show (Fragment fragment) | 
分离和重建Fragment视图
分离并不是把把Fragment删除, 只是把Fragment的显示内容移除了而已.
| 1 2 | FragmentTransaction detach (Fragment fragment) // 分离视图 FragmentTransaction attach (Fragment fragment) // 重建视图 | 
添加到返回栈
如果执行了该方法, 在按下返回键后将退出当前Fragment而不是Activity
| 1 | FragmentTransaction addToBackStack (String name) | 
过渡动画
设置默认的动画效果
支持字段:
TRANSIT_NONE 无动画效果
TRANSIT_FRAGMENT_OPEN 默认的开启动画效果
TRANSIT_FRAGMENT_CLOSE 默认的关闭动画效果
TRANSIT_FRAGMENT_FADE. 渐隐效果
| 1 | FragmentTransaction setTransition (int transit) | 
设置自定义的动画效果
| 1 2 3 4 5 6 7 | FragmentTransaction setCustomAnimations (int enter, // 进入动画xml int exit) // 退出动画xml FragmentTransaction setCustomAnimations (int enter,  int exit,  int popEnter, // 这是Fragment处于返回栈时的进入和退出动画 int popExit) | 
提交事务
这个没什么好说的. 不提交的话一切操作都无效
| 1 | int commit () | 
与Activity的交互
Fragment内部提供方法getActivity()直接获取其依附的Activity的实例. 借此数据传递或者是与该Activity上的其他Fragment进行交互都没有任何阻碍.
数据的保存和恢复
Fragment异常退出保存和恢复
保存和Activity一样
| 1 | void onSaveInstanceState (Bundle outState) | 
恢复数据重写以下方法即可
| 1 2 | void onCreate (Bundle savedInstanceState) void onActivityCreated (Bundle savedInstanceState) | 
Fragment重建保存和恢复
在横竖屏切换或者Activity重建时, Activity其依附的Fragment也会同样的销毁重建. 一般会在AndroidManifest的Activity标签中加入属性android:configChanges="orientation"禁止重新创建.
以下方法进行数据的保存和获取同样可以达到数据保存的目的.
| 1 2 | Bundle getArguments () void setArguments (Bundle args) | 
Fragment对象保存和恢复
该方法在Activity重新创建的时候能够保存和恢复Fragment的实例对象.
| 1 2 | boolean getRetainInstance () void setRetainInstance (boolean retain) | 
使用这种方式进行实例的保存和恢复会导致Fragment的生命周期发生变化
- onDestroy方法不会被执行, 但是onDetach会执行
- onCreate不会执行
- 其他生命周期方法正常
应用场景:
有时候Activity利用onSavaInstanceState来保存数据, 但是该方法是通过Bundle对象来存储数据的, Bundle对于大数据的处理会相当卡顿, 这个时候就需要用Fragment来进行保存和恢复. 如果单单是为了保存和恢复而创建的Fragment可以不需要创建布局文件. 因为不需要视图显示.
创建菜单
Fragment也提供和Activity一样的菜单创建和选择回调用法, 同样的支持向顶栏添加菜单, 不过在创建View对象之前调用setHasOptionsMenu(true);, 否则无法创建菜单
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class FragmentA extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 如果不设为true Fragment不会调用onCreateOptionMenu setHasOptionsMenu(true); return inflater.inflate(R.layout.fragement_a, null); } /** * 和Activity一样, 在这里创建方法 * @param menu * @param inflater */ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.fragment_menu, menu); super.onCreateOptionsMenu(menu, inflater); } /** * 菜单选项被选择是回调的方法 * @param item * @return */ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } } | 
生命周期
依附Activity生命周期
片段必须始终嵌入在 Activity 中,其生命周期直接受宿主 Activity 生命周期的影响。
例如,当 Activity 暂停时,其中的所有片段也会暂停;当 Activity 被销毁时,所有片段也会被销毁。和Activity同名的方法作用也相同.
我就介绍下不同的生命周期方法吧:
- onAttach方法:Fragment和Activity建立关联的时候调用。
- onCreateView方法:为Fragment加载布局时调用。
- onActivityCreated方法:当Activity中的onCreate方法执行完后调用。
- onDestroyView方法:Fragment中的布局被移除时调用。
- onDetach方法:Fragment和Activity解除关联的时候调用。
场景演示
切换到该Fragment:
11-29 14:26:35.095: D/AppListFragment(7649): onAttach
11-29 14:26:35.095: D/AppListFragment(7649): onCreate
11-29 14:26:35.095: D/AppListFragment(7649): onCreateView
11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated
11-29 14:26:35.120: D/AppListFragment(7649): onStart
11-29 14:26:35.120: D/AppListFragment(7649): onResume
屏幕灭掉:
11-29 14:27:35.185: D/AppListFragment(7649): onPause
11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState
11-29 14:27:35.205: D/AppListFragment(7649): onStop
屏幕解锁
11-29 14:33:13.240: D/AppListFragment(7649): onStart
11-29 14:33:13.275: D/AppListFragment(7649): onResume
切换到其他Fragment:
11-29 14:33:33.655: D/AppListFragment(7649): onPause
11-29 14:33:33.655: D/AppListFragment(7649): onStop
11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView
切换回本身的Fragment:
11-29 14:33:55.820: D/AppListFragment(7649): onCreateView
11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated
11-29 14:33:55.825: D/AppListFragment(7649): onStart
11-29 14:33:55.825: D/AppListFragment(7649): onResume
回到桌面
11-29 14:34:26.590: D/AppListFragment(7649): onPause
11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState
11-29 14:34:26.880: D/AppListFragment(7649): onStop
回到应用
11-29 14:36:51.940: D/AppListFragment(7649): onStart
11-29 14:36:51.940: D/AppListFragment(7649): onResume
退出应用
11-29 14:37:03.020: D/AppListFragment(7649): onPause
11-29 14:37:03.155: D/AppListFragment(7649): onStop
11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView
11-29 14:37:03.165: D/AppListFragment(7649): onDestroy
11-29 14:37:03.165: D/AppListFragment(7649): onDetach
 
                     
                    
                 
                    
                



 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号