Android Fragment真正的完全解析(下)

来源:互联网 发布:蜘蛛纸牌算法 编辑:程序博客网 时间:2024/06/05 00:38

转载请标明出处:http : //blog.csdn.net/lmj623565791/article/details/37992017

上篇博客中已经介绍了片段产生原因,以及一些基本的用法和各种API,如果你还不了解,请看Android Fragment真正的完全解析(上)。

本篇将介绍上篇博客提到的:如何管理片段回退栈,片段如何与活动交互,片段与活动交互的最佳实践,没有视图的片段的用处,使用片段创建对话框,如何与动作条,菜单项集成等~~

如图1所示,管理片段回退栈

类似与Android的系统为活动维护一个任务栈,我们也可以通过活动维护一个回退栈来保存每次片段事务发生的变化。如果你将片段任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的片段。一旦片段完全从后退栈中弹出,用户再次点击后退键,则退出当前活动。

看这样一个效果图:


点击第一个按钮,切换到第二个界面,点击第二个按钮,切换到第三个界面,然后点击后退键依次回退。这像不像初学的Android时的活动跳转,当然了,这里肯定不是,不然我就跪了。这里是片段实现的,用户点击后退,实际是片段回退栈不断的弹栈。

如何添加一个片段事务到回退栈:

FragmentTransaction.addToBackStack(字符串)

下面讲解代码:很明显一共是3个片段和一个活动。

先看活动的布局文件:

[html] 查看纯文本 
  1. RelativeLayout xmlns:android “http://schemas.android.com/apk/res/android”   
  2.     xmlns:tools “http://schemas.android.com/tools”  
  3.     android:layout_width “match_parent”  
  4.     android:layout_height “match_parent” >   
  5.   
  6.     FrameLayout  
  7.         android:id “@ + id / id_content”  
  8.         android:layout_width “fill_parent”  
  9.         android:layout_height “fill_parent” >   
  10.     </ FrameLayout >  
  11.   
  12. </ RelativeLayout >  
不同的片段就在这个的FrameLayout中显示。

MainActivity.java

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Activity;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.view.Window;  
  8.   
  9. 公共 MainActivity  扩展了 Activity   
  10. {  
  11.   
  12.   
  13.     @覆盖  
  14.     protected void  onCreate(Bundle savedInstanceState)   
  15.     {  
  16.         超级.onCreate(savedInstanceState);  
  17.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  18.         的setContentView(R.layout.activity_main);  
  19.   
  20.         FragmentManager fm = getFragmentManager();  
  21.         FragmentTransaction tx = fm.beginTransaction();  
  22.         tx.add(R.id.id_content,  new  FragmentOne(),“ONE” );  
  23.         tx.commit();  
  24.     }  
  25.   
  26. }  
很简单,直接将FragmentOne添加到布局文件中的的FrameLayout中,注意这里并没有调用FragmentTransaction.addToBackStack(字符串),因为我不喜欢在当前显示时,点击返回键出现白板。而是正确的相应返回键,即退出我们的活性的影响。

下面是FragmentOne

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.view.LayoutInflater;  
  8. 导入 android.view.View;  
  9. 导入 android.view.View.OnClickListener;  
  10. 导入 android.view.ViewGroup;  
  11. 导入 android.widget.Button;  
  12.   
  13. public class  FragmentOne  extends  Fragment  实现 OnClickListener   
  14. {  
  15.   
  16.     私人 按钮mBtn;  
  17.   
  18.     @覆盖  
  19.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  20.             Bundle savedInstanceState)  
  21.     {  
  22.         查看view = inflater.inflate(R.layout.fragment_one,container,  false );  
  23.         mBtn =(Button)view.findViewById(R.id.id_fragment_one_btn);  
  24.         mBtn.setOnClickListener(this );  
  25.         返回 视图;  
  26.     }  
  27.   
  28.     @覆盖  
  29.     public void  onClick(View v)   
  30.     {  
  31.         FragmentTwo fTwo =  new  FragmentTwo();  
  32.         FragmentManager fm = getFragmentManager();  
  33.         FragmentTransaction tx = fm.beginTransaction();  
  34.         tx.replace(R.id.id_content,fTwo,  “TWO” );  
  35.         tx.addToBackStack(null );  
  36.         tx.commit();  
  37.   
  38.     }  
  39.   
  40. }  

我们在点击FragmentOne中的按钮时,使用了替代方法,如果你看了前一篇博客,一定记得更换是删除和添加的合体,并且如果不添加事务到回退栈,前一个片段实例会被销毁。这里很明显,我们调用tx.addToBackStack(NULL);将当前的事务添加到了回退栈,所以FragmentOne实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView,证据就是:仔细看上面的效果图,我们在跳转前在文本框输入的内容,在用户返回得到第一个界面的时候不见了。

接下来FragmentTwo

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.view.LayoutInflater;  
  8. 导入 android.view.View;  
  9. 导入 android.view.View.OnClickListener;  
  10. 导入 android.view.ViewGroup;  
  11. 导入 android.widget.Button;  
  12.   
  13. 公共 FragmentTwo  扩展 Fragment  实现 OnClickListener   
  14. {  
  15.   
  16.     私人 按钮mBtn;  
  17.     @覆盖  
  18.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  19.             Bundle savedInstanceState)  
  20.     {  
  21.         查看视图= inflater.inflate(R.layout.fragment_two,container,  false );  
  22.         mBtn =(Button)view.findViewById(R.id.id_fragment_two_btn);  
  23.         mBtn.setOnClickListener(this );  
  24.         返回 视图;   
  25.     }  
  26.     @覆盖  
  27.     public void  onClick(View v)   
  28.     {  
  29.         FragmentThree fThree =  new  FragmentThree();  
  30.         FragmentManager fm = getFragmentManager();  
  31.         FragmentTransaction tx = fm.beginTransaction();  
  32.         tx.hide(this );  
  33.         tx.add(R.id.id_content,fThree,  “THREE” );  
  34. // tx.replace(R.id.id_content,fThree,“THREE”);  
  35.         tx.addToBackStack(null );  
  36.         tx.commit();  
  37.     }  
  38.   
  39.   
  40. }  

这里点击时,我们没有使用替换,而是先隐藏了当前的片段,然后添加了FragmentThree的实例,最后将事务添加到回退栈这样做的目的是为了给大家提供一种方案:如果不希望视图重绘该怎么做,请再次仔细看效果图,我们在FragmentTwo的EditText上填写的内容,用户后退回来时,数据还在~~~

最后FragmentThree就是简单的面包了:

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.os.Bundle;  
  5. 导入 android.view.LayoutInflater;  
  6. 导入 android.view.View;  
  7. 导入 android.view.View.OnClickListener;  
  8. 导入 android.view.ViewGroup;  
  9. 导入 android.widget.Button;  
  10. 导入 android.widget.Toast;  
  11.   
  12. 公共 FragmentThree  扩展 Fragment  实现 OnClickListener   
  13. {  
  14.   
  15.     私人 按钮mBtn;  
  16.   
  17.     @覆盖  
  18.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  19.             Bundle savedInstanceState)  
  20.     {  
  21.         查看view = inflater.inflate(R.layout.fragment_three,container,  false );  
  22.         mBtn =(Button)view.findViewById(R.id.id_fragment_three_btn);  
  23.         mBtn.setOnClickListener(this );  
  24.         返回 视图;  
  25.     }  
  26.   
  27.     @覆盖  
  28.     public void  onClick(View v)   
  29.     {  
  30.         Toast.makeText(getActivity(),  “我是片段三中的btn” ,  
  31.                 Toast.LENGTH_SHORT).show();  
  32.     }  
  33.   
  34. }  

好了,经过上面的介绍,应该已经知道片段回退栈是怎么一回事了,以及隐藏,更换等各自的应用的场景。

这里极其注意一点:上面的整体代码不具有任何参考价值,纯粹为了显示回退栈,在后面讲解了片段与活动通信以后,会重构上面的代码!

2,片段与活动通信

因为所有的片段都是依附于活动的,所以通信起来并不复杂,大概归纳为:

一,如果你的活动中包含自己管理的片段的引用,可以通过引用直接访问所有的碎片的公共方法

B,如果活动中未保存任何片段的引用,那么没关系,每个片段都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何片段实例,然后进行操作。

C,在片段中可以通过getActivity得到当前绑定的活动的实例,然后进行操作。

注:如果在片段中需要上下文,可以通过调用getActivity(),如果该上下文需要在活动被销毁后还存在,则使用getActivity()getApplicationContext()。

3,片段与活动通信的最佳实践

因为要考虑片段的重复使用,所以必须降低片段与活动的耦合,而且片段更不应该直接操作别的片段,毕竟片段操作应该由它的管理者活动来决定。

下面我通过两种方式的代码,分别重构,FragmentOne和FragmentTwo的点击事件,以及活动对点击事件的响应:

首先看FragmentOne

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.os.Bundle;  
  5. 导入 android.view.LayoutInflater;  
  6. 导入 android.view.View;  
  7. 导入 android.view.View.OnClickListener;  
  8. 导入 android.view.ViewGroup;  
  9. 导入 android.widget.Button;  
  10.   
  11. public class  FragmentOne  extends  Fragment  实现 OnClickListener   
  12. {  
  13.     私人 按钮mBtn;  
  14.   
  15.     / ** 
  16.      *设置按钮点击的回调 
  17.      * @author zhy 
  18.      * 
  19.      * /  
  20.     公共接口 FOneBtnClickListener   
  21.     {  
  22.         void  onFOneBtnClick();  
  23.     }  
  24.   
  25.     @覆盖  
  26.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  27.             Bundle savedInstanceState)  
  28.     {  
  29.         查看view = inflater.inflate(R.layout.fragment_one,container,  false );  
  30.         mBtn =(Button)view.findViewById(R.id.id_fragment_one_btn);  
  31.         mBtn.setOnClickListener(this );  
  32.         返回 视图;  
  33.     }  
  34.   
  35.     / ** 
  36.      *交给宿主活动处理,如果它希望处理 
  37.      * /  
  38.     @覆盖  
  39.     public void  onClick(View v)   
  40.     {  
  41.         if  (getActivity()  instanceof  FOneBtnClickListener)  
  42.         {  
  43.             ((FOneBtnClickListener)getActivity())。onFOneBtnClick();  
  44.         }  
  45.     }  
  46.   
  47. }  

可以看到现在的FragmentOne不和任何活动耦合,任何活动都可以使用;并且我们声明了一个接口,来回调其点击事件,想要管理其点击事件的活动实现此接口就即可可以看到我们在的onClick中首先判断了当前绑定的活动是否实现了该接口,如果实现了则调用。

再看FragmentTwo

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.os.Bundle;  
  5. 导入 android.view.LayoutInflater;  
  6. 导入 android.view.View;  
  7. 导入 android.view.View.OnClickListener;  
  8. 导入 android.view.ViewGroup;  
  9. 导入 android.widget.Button;  
  10.   
  11. 公共 FragmentTwo  扩展 Fragment  实现 OnClickListener   
  12. {  
  13.   
  14.       
  15.     私人 按钮mBtn;  
  16.       
  17.     私有 FTwoBtnClickListener fTwoBtnClickListener;  
  18.       
  19.     公共接口 FTwoBtnClickListener   
  20.     {  
  21.         void  onFTwoBtnClick();  
  22.     }  
  23.     //设置回调接口  
  24.     public void  setfTwoBtnClickListener(FTwoBtnClickListener fTwoBtnClickListener)   
  25.     {  
  26.         这个.fTwoBtnClickListener = fTwoBtnClickListener;  
  27.     }  
  28.     @覆盖  
  29.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  30.             Bundle savedInstanceState)  
  31.     {  
  32.         查看视图= inflater.inflate(R.layout.fragment_two,container,  false );  
  33.         mBtn =(Button)view.findViewById(R.id.id_fragment_two_btn);  
  34.         mBtn.setOnClickListener(this );  
  35.         返回 视图;   
  36.     }  
  37.     @覆盖  
  38.     public void  onClick(View v)   
  39.     {  
  40.         if (fTwoBtnClickListener!=  null )  
  41.         {  
  42.             fTwoBtnClickListener.onFTwoBtnClick();  
  43.         }  
  44.     }  
  45.   
  46. }  

与FragmentOne极其类似,但是我们提供了setListener这样的方法,意味着活性不仅需要实现该接口,还必须显示调用mFTwo.setfTwoBtnClickListener(本)。

最后看活动:

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Activity;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.view.Window;  
  8.   
  9. import  com.zhy.zhy_fragments.FragmentOne.FOneBtnClickListener;  
  10. import  com.zhy.zhy_fragments.FragmentTwo.FTwoBtnClickListener;  
  11.   
  12. public class  MainActivity  extends  Activity  implements  FOneBtnClickListener,   
  13.         FTwoBtnClickListener  
  14. {  
  15.   
  16.     私人 FragmentOne mFOne;  
  17.     私人 FragmentTwo mFTwo;  
  18.     私人 FragmentThree mFThree;  
  19.   
  20.     @覆盖  
  21.     protected void  onCreate(Bundle savedInstanceState)   
  22.     {  
  23.         超级.onCreate(savedInstanceState);  
  24.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  25.         的setContentView(R.layout.activity_main);  
  26.   
  27.         mFOne =  new  FragmentOne();  
  28.         FragmentManager fm = getFragmentManager();  
  29.         FragmentTransaction tx = fm.beginTransaction();  
  30.         tx.add(R.id.id_content,mFOne,  “ONE” );  
  31.         tx.commit();  
  32.     }  
  33.   
  34.     / ** 
  35.      * FragmentOne按钮点击时的回调 
  36.      * /  
  37.     @覆盖  
  38.     public void  onFOneBtnClick()   
  39.     {  
  40.   
  41.         if  (mFTwo ==  null )  
  42.         {  
  43.             mFTwo =  new  FragmentTwo();  
  44.             mFTwo.setfTwoBtnClickListener(this );  
  45.         }  
  46.         FragmentManager fm = getFragmentManager();  
  47.         FragmentTransaction tx = fm.beginTransaction();  
  48.         tx.replace(R.id.id_content,mFTwo,  “TWO” );  
  49.         tx.addToBackStack(null );  
  50.         tx.commit();  
  51.     }  
  52.   
  53.     / ** 
  54.      * FragmentTwo按钮点击时的回调 
  55.      * /  
  56.     @覆盖  
  57.     public void  onFTwoBtnClick()   
  58.     {  
  59.         if  (mFThree ==  null )  
  60.         {  
  61.             mFThree =  new  FragmentThree();  
  62.   
  63.         }  
  64.         FragmentManager fm = getFragmentManager();  
  65.         FragmentTransaction tx = fm.beginTransaction();  
  66.         tx.hide(mFTwo);  
  67.         tx.add(R.id.id_content,mFThree,  “THREE” );  
  68.         // tx.replace(R.id.id_content,fThree,“THREE”);  
  69.         tx.addToBackStack(null );  
  70.         tx.commit();  
  71.     }  
  72.   
  73. }  

代码重构结束,与开始的效果一模一样上面两种通信方式都是值得推荐的,随便选择一种自己喜欢的这里再提一下:。虽然片段和活性可以通过getActivity与findFragmentByTag或者findFragmentById,进行任何操作,甚至在片段里面操作另外的片段,但是没有特殊理由是绝对不提倡的.Activity担任的是片段间类似总线一样的角色,应当由它决定片段如何操作。另外虽然片段不能响应意图打开,但是活动可以,活动可以接收意图,然后根据参数判断显示哪个片段。

4,如何处理运行时配置发生变化

运行时配置发生变化,最常见的就是屏幕发生旋转,如果你不知道如何处理屏幕变化可以参考:Android屏幕旋转处理AsyncTask和ProgressDialog的最佳方案

这里提一下:很多人觉得强制设置屏幕的方向就可以了,但是有一点,当你的应用被至于后台(例如用户点击了家),长时间没有返回的时候,你的应用也会被重新启动。比如上例:如果你把上面的例子你至于FragmentThree界面,然后处于后台状态,长时间后你会发现当你再次通过家里打开时,上面FragmentThree与FragmentOne叠加在一起,这就是因为你的活动重新启动,在原来的FragmentThree上又绘制了一个FragmentOne。

好了,下面看一段代码:

活动:

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Activity;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.view.Window;  
  8.   
  9. 公共 MainActivity  扩展了 Activity   
  10.   
  11. {  
  12.     私人 FragmentOne mFOne;  
  13.   
  14.     @覆盖  
  15.     protected void  onCreate(Bundle savedInstanceState)   
  16.     {  
  17.         超级.onCreate(savedInstanceState);  
  18.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  19.         的setContentView(R.layout.activity_main);  
  20.   
  21.         mFOne =  new  FragmentOne();  
  22.         FragmentManager fm = getFragmentManager();  
  23.         FragmentTransaction tx = fm.beginTransaction();  
  24.         tx.add(R.id.id_content,mFOne,  “ONE” );  
  25.         tx.commit();  
  26.   
  27.     }  
  28.   
  29. }  

分段

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.os.Bundle;  
  5. 导入 android.util.Log;  
  6. 导入 android.view.LayoutInflater;  
  7. 导入 android.view.View;  
  8. 导入 android.view.ViewGroup;  
  9.   
  10. 公共 FragmentOne  扩展 片段   
  11. {  
  12.     private static final  String TAG =  “FragmentOne” ;    
  13.   
  14.     @覆盖  
  15.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  16.             Bundle savedInstanceState)  
  17.     {  
  18.         Log.e(TAG,  “onCreateView” );  
  19.         查看view = inflater.inflate(R.layout.fragment_one,container,  false );  
  20.         返回 视图;  
  21.     }  
  22.   
  23.     @覆盖  
  24.     public void  onCreate(Bundle savedInstanceState)   
  25.     {  
  26.         // TODO自动生成的方法存根  
  27.         超级.onCreate(savedInstanceState);  
  28.   
  29.         Log.e(TAG,  “onCreate” );  
  30.     }  
  31.   
  32.     @覆盖  
  33.     public void  onDestroyView()   
  34.     {  
  35.         // TODO自动生成的方法存根  
  36.         超级.onDestroyView();  
  37.         Log.e(TAG,  “onDestroyView” );  
  38.     }  
  39.   
  40.     @覆盖  
  41.     public void  onDestroy()   
  42.     {  
  43.         // TODO自动生成的方法存根  
  44.         超级.onDestroy();  
  45.         Log.e(TAG,  “onDestroy” );  
  46.     }  
  47.   
  48. }  

很简单的代码,当你运行之后,不断的旋转屏幕,你会发现每旋转一次屏幕,屏幕上就多了一个FragmentOne的实例,并且后台日志会打印出许多套生命周期的回调。

类似:

[html] 查看纯文本 
  1. 07-20 08:18:46.651:E / FragmentOne(1633):onCreate  
  2. 07-20 08:18:46.651:E / FragmentOne(1633):onCreate  
  3. 07-20 08:18:46.651:E / FragmentOne(1633):onCreate  
  4. 07-20 08:18:46.681:E / FragmentOne(1633):onCreateView  
  5. 07-20 08:18:46.831:E / FragmentOne(1633):onCreateView  
  6. 07-20 08:18:46.891:E / FragmentOne(1633):onCreateView  

这是为什么呢,因为当屏幕发生旋转,活动发生重新启动,默认的活动中的片段也会跟着活动重新创建;这样造成当旋转的时候,本身存在的片段会重新启动,然后当执行活动的的onCreate时,又会再次实例化一个新的片段,这就是出现的原因。

那么如何解决呢:

其实通过检查onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建:

默认的savedInstanceState会存储一些数据,包括片段的实例:通过打印可以看出:

[java] 查看纯文本 
  1. 07 20 08 23 12.952 :E / FragmentOne(1782 ):Bundle [{android:fragments = android.app.FragmentManagerState @ 40d0b7b8 ,android:viewHierarchyState = Bundle [{android:focusedViewId = 2131230721 ,android:views = util.SparseArray @ 40d0af68 }]}]   
所以,我们简单改一下代码,只有在savedInstanceState == NULL时,才进行创建片段实例:

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Activity;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.util.Log;  
  8. 导入 android.view.Window;  
  9.   
  10. 公共 MainActivity  扩展了 Activity   
  11.   
  12. {  
  13.     private static final  String TAG =  “FragmentOne” ;    
  14.     私人 FragmentOne mFOne;  
  15.   
  16.     @覆盖  
  17.     protected void  onCreate(Bundle savedInstanceState)   
  18.     {  
  19.         超级.onCreate(savedInstanceState);  
  20.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  21.         的setContentView(R.layout.activity_main);  
  22.   
  23.         Log.e(TAG,savedInstanceState + “” );  
  24.           
  25.         if (savedInstanceState ==  null )  
  26.         {  
  27.             mFOne =  new  FragmentOne();  
  28.             FragmentManager fm = getFragmentManager();  
  29.             FragmentTransaction tx = fm.beginTransaction();  
  30.             tx.add(R.id.id_content,mFOne,  “ONE” );  
  31.             tx.commit();  
  32.         }  
  33.           
  34.           
  35.   
  36.     }  
  37.   
  38. }  

现在无论进行多次旋转都只会有一个片段实例在活动中。

现在还存在一个问题,就是重新绘制时,片段发生重建,原本的数据如何保持?

其实和活性类似,片段也有的onSaveInstanceState的方法,在此方法中进行保存数据,然后在的onCreate或者onCreateView或者onActivityCreated进行恢复都可以。

由于篇幅原因,贴就不测试代码了。

5,Fragmeny与动作条和菜单项集成

片段可以添加自己的菜单项到活动的动作条或者可选菜单中。

一个,在片段的的onCreate中调用 setHasOptionsMenu(真);

B,然后在片段子类中实现onCreateOptionsMenu

C,如果希望在片段中处理菜单项的点击,也可以实现onOptionsItemSelected;当然了活动也可以直接处理该菜单项的点击事件。

代码:

分段

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Fragment;  
  4. 导入 android.os.Bundle;  
  5. 导入 android.view.LayoutInflater;  
  6. 导入 android.view.Menu;  
  7. 导入 android.view.MenuInflater;  
  8. 导入 android.view.MenuItem;  
  9. 导入 android.view.View;  
  10. 导入 android.view.ViewGroup;  
  11. 导入 android.widget.Toast;  
  12.   
  13. 公共 FragmentOne  扩展 片段   
  14. {  
  15.   
  16.     @覆盖  
  17.     public void  onCreate(Bundle savedInstanceState)   
  18.     {  
  19.         超级.onCreate(savedInstanceState);  
  20.         setHasOptionsMenu(true );  
  21.     }  
  22.   
  23.     @覆盖  
  24.     public  View onCreateView(LayoutInflater inflater,ViewGroup容器,  
  25.             Bundle savedInstanceState)  
  26.     {  
  27.         查看view = inflater.inflate(R.layout.fragment_one,container,  false );  
  28.         返回 视图;  
  29.     }  
  30.   
  31.     @覆盖  
  32.     public void  onCreateOptionsMenu(菜单菜单,MenuInflater inflater)   
  33.     {  
  34.         inflater.inflate(R.menu.fragment_menu,menu);  
  35.     }  
  36.   
  37.     @覆盖  
  38.     public boolean  onOptionsItemSelected(MenuItem item)   
  39.     {  
  40.         switch  (item.getItemId())  
  41.         {  
  42.         case  R.id.id_menu_fra_test:  
  43.             Toast.makeText(getActivity(),  “FragmentMenuItem1” ,Toast.LENGTH_SHORT).show();  
  44.             打破;  
  45.         }  
  46.         返回;   
  47.     }  
  48.   
  49. }  

活动

[java] 查看纯文本 
  1.  com.zhy.zhy_fragments;  
  2.   
  3. 导入 android.app.Activity;  
  4. 导入 android.app.FragmentManager;  
  5. 导入 android.app.FragmentTransaction;  
  6. 导入 android.os.Bundle;  
  7. 导入 android.util.Log;  
  8. 导入 android.view.Menu;  
  9. 导入 android.view.MenuItem;  
  10. 导入 android.view.Window;  
  11. 导入 android.widget.Toast;  
  12.   
  13. 公共 MainActivity  扩展了 Activity   
  14.   
  15. {  
  16.     private static final  String TAG =  “FragmentOne” ;    
  17.     私人 FragmentOne mFOne;  
  18.   
  19.     @覆盖  
  20.     protected void  onCreate(Bundle savedInstanceState)   
  21.     {  
  22.         超级.onCreate(savedInstanceState);  
  23.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  24.         的setContentView(R.layout.activity_main);  
  25.   
  26.         Log.e(TAG,savedInstanceState +  “” );  
  27.   
  28.         if  (savedInstanceState ==  null )  
  29.         {  
  30.             mFOne =  new  FragmentOne();  
  31.             FragmentManager fm = getFragmentManager();  
  32.             FragmentTransaction tx = fm.beginTransaction();  
  33.             tx.add(R.id.id_content,mFOne,  “ONE” );  
  34.             tx.commit();  
  35.         }  
  36.   
  37.     }  
  38.   
  39.     @覆盖  
  40.     public boolean  onCreateOptionsMenu(菜单菜单)   
  41.     {  
  42.         超级.onCreateOptionsMenu(菜单);  
  43.         getMenuInflater()。inflate(R.menu.main,menu);  
  44.         返回;   
  45.     }  
  46.   
  47.     @覆盖  
  48.     public boolean  onOptionsItemSelected(MenuItem item)   
  49.     {  
  50.         switch  (item.getItemId())  
  51.         {  
  52.         案例 R.id.action_settings:  
  53.             Toast.makeText(this ,  “setting” ,Toast.LENGTH_SHORT).show();  
  54.             返回;   
  55.         默认值:  
  56.             //如果希望片段自己处理菜单项点击事件,一定不要忘了调用super.xxx  
  57.             返回超级.onOptionsItemSelected(item);   
  58.         }  
  59.     }  
  60.   
  61. }  

效果图:

好了,可以很好的看到,片段可以添加菜单项,也可以自己处理点击~~~

如图6所示,没有布局的片段的作用

没有布局文件片段实际上是为了保存,当活动重启时,保存大量数据准备的

请参考博客:Android屏幕旋转处理AsyncTask和ProgressDialog的最佳方案

如图7所示,使用片段创建对话框

这是Google推荐的方式,我也单独写过博客介绍,请参考:Android官方推荐:DialogFragment创建对话框


原创粉丝点击