Android记录23-关于actionbar中overflow menu(溢出菜单)中的一些问题

来源:互联网 发布:静态个人引导页源码 编辑:程序博客网 时间:2024/05/21 08:51

前言

本篇博客记录一下小巫在使用actionbar的时候遇到关于溢出菜单的一些问题:

  1. 什么是Overflow menu
  2. Android 3.0以上默认不显示overflow menu
  3. 如何强制在Android 4.4.4以下的手机显示overflow menu
  4. 经测试,魅族手机无法强制显示overflow menu,其他手机暂无发现这种问题

先来两张对比图:


左边是红米手机的效果,右边是针对魅族Mx4pro做的适配效果。

什么是overflow menu?

先来解释一下什么是overflow menu,中文叫做“溢出菜单”,顾名思义溢出的菜单,我们有些手机是有实体按键或虚拟按键,其中一个是菜单键,有的可能没有,例如魅族就只有一个back的返回虚拟键。点击菜单键的时候,就会在底部弹出溢出菜单,在Android 3.0之后,也就是API 11之后才可以加入ActionBar控件的,再其右上角会有三个点,那个就是我们说的overflow menu,我们在menu中定义菜单项就可以弹出类似上面红米手机弹出的效果。关于ActionBar有很多用法,本篇博客就不展开讲,有兴趣的同学可以到官网进行学习。



如何在ActionBar强制显示溢出菜单?

Android 3.0以上的手机默认是不显示溢出菜单的,那如何强制在Android 4.4以下的手机显示溢出菜单呢?可以使用以下方法:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // 强制actionbar显示overflow菜单  
  2.     // force to show overflow menu in actionbar for android 4.4 below  
  3.     private void getOverflowMenu() {  
  4.         try {  
  5.             ViewConfiguration config = ViewConfiguration.get(this);  
  6.             Field menuKeyField = ViewConfiguration.class  
  7.                     .getDeclaredField("sHasPermanentMenuKey");  
  8.             if (menuKeyField != null) {  
  9.                 menuKeyField.setAccessible(true);  
  10.                 menuKeyField.setBoolean(config, false);  
  11.             }  
  12.         } catch (Exception e) {  
  13.             e.printStackTrace();  
  14.         }  
  15.     }  


适配类似魅族手机无法显示溢出菜单的解决方案

上面已经解决了如何在Android 4.4以下的手机强制显示溢出菜单,下面来解决一些奇葩手机无法显示溢出菜单的问题。为什么魅族手机无法显示,了解到的是魅族没有所谓的actionbar,它们称为smartbar,看来是魅族的工程师把官方的actionbar进行了修改。一个字,坑!不过小巫想到了一个解决办法,我们每部手机都有自己的手机品牌,我们可以针对这些奇葩手机进行适配,溢出菜单我们就使用popupwindow来替代

获得手机信息
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 获取IMEI号,IESI号,手机型号 
  3.      */  
  4.     public static void getInfo(Context context) {  
  5.         TelephonyManager mTm = (TelephonyManager) context  
  6.                 .getSystemService(Context.TELEPHONY_SERVICE);  
  7.         String imei = mTm.getDeviceId();  
  8.         String imsi = mTm.getSubscriberId();  
  9.         String mtype = android.os.Build.MODEL; // 手机型号  
  10.         String mtyb = android.os.Build.BRAND;// 手机品牌  
  11.         String numer = mTm.getLine1Number(); // 手机号码,有的可得,有的不可得  
  12.         Log.i("text""手机IMEI号:" + imei + "手机IESI号:" + imsi + "手机型号:" + mtype  
  13.                 + "手机品牌:" + mtyb + "手机号码" + numer);  
  14.     }  

获取手机品牌
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 得到手机品牌 
  3.      * @return 
  4.      */  
  5.     public static String getPhoneBrand() {  
  6.         return android.os.Build.BOARD;  
  7.     }  

得到手机品牌之后,我们就在创建溢出菜单的时候进行判断:
1. 如果是魅族手机,则加载自定义菜单
2. 如果不是,则使用系统的溢出菜单,加载菜单内容

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {  
  3.         // Inflate the menu; this adds items to the action bar if it is present.  
  4.         super.onCreateOptionsMenu(menu, inflater);  
  5.         String brand = PhoneUtils.getPhoneBrand();  
  6.         if ("mx4pro".equals(brand)) {  
  7.             inflater.inflate(R.menu.overflow_menu, menu);  
  8.         } else {  
  9.             inflater.inflate(R.menu.main, menu);  
  10.         }  
  11.     }  


溢出菜单文件
/res/menu/main.xm
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >  
  2.   
  3.         <item  
  4.             android:id="@+id/menu_hotest"  
  5.             android:orderInCategory="100"  
  6.             android:showAsAction="never"  
  7.             android:title="@string/menu_hotest"/>  
  8.         <item  
  9.             android:id="@+id/menu_lastest"  
  10.             android:orderInCategory="100"  
  11.             android:showAsAction="never"  
  12.             android:title="@string/menu_lastest"/>  
  13.   
  14. </menu>  

自定义的菜单文件
/res/menu/overflow_menu.xml
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.   
  4.     <item  
  5.         android:id="@+id/menu_overflow"  
  6.         android:icon="@drawable/ic_more"  
  7.         android:orderInCategory="100"  
  8.         android:showAsAction="always"  
  9.         android:title="@string/menu_overflow">  
  10.     </item>  
  11.   
  12. </menu>  
自定义菜单就直接给它设置一个actionbar的按钮,图标是那三个点


我们在选中菜单的时候执行我们的业务逻辑
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public boolean onOptionsItemSelected(MenuItem item) {  
  3.     switch (item.getItemId()) {  
  4.     case R.id.menu_overflow:  
  5.         popupOverflowMenu();  
  6.         return true;  
  7.     case R.id.menu_lastest:  
  8.         type = "latest";  
  9.         break;  
  10.     case R.id.menu_hotest:  
  11.         type = "hotest";  
  12.         break;  
  13.     default:  
  14.         break;  
  15.     }  
  16.     return super.onOptionsItemSelected(item);  
  17. }  

如果是魅族mx4pro手机,就弹出我们的自定义菜单,下面是实现:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 弹出自定义溢出菜单 
  3.      */  
  4.     public void popupOverflowMenu() {  
  5.         // 显示溢出菜单的时候设置背景半透明  
  6.         setWindowAlpha(0.5f);   
  7.         // 获取状态栏高度  
  8.         Rect frame = new Rect();  
  9.         getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
  10.         // 状态栏高度 frame.top  
  11.         int xOffset = frame.top + getActivity().getActionBar().getHeight() - 25// 减去阴影宽度,适配UI  
  12.         int yOffset = Dp2Dx(getActivity(), 8f); // 设置x方向offset为5dp  
  13.         View parentView = getActivity().getLayoutInflater().inflate(R.layout.fragment_portfolio, null);  
  14.         View popView = getActivity().getLayoutInflater().inflate(R.layout.action_overflow_menu, null);  
  15.         // popView即popupWindow布局  
  16.         PopupWindow popupWindow = new PopupWindow(popView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);  
  17.         // 必须设计BackgroundDrawable后setOutsideTouchable(true)才会有效。这里在XML中定义背景,所以这里为null  
  18.         popupWindow.setBackgroundDrawable(new ColorDrawable(0000000000));  
  19.         popupWindow.setFocusable(true);  
  20.         popupWindow.setOutsideTouchable(true); // 点击外部关闭  
  21.         popupWindow.setAnimationStyle(android.R.style.Animation_Dialog);  
  22.         // 设置Gravity,让它显示在右上角  
  23.         popupWindow.showAtLocation(parentView, Gravity.RIGHT | Gravity.TOP, yOffset, xOffset);  
  24.         popupWindow.setOnDismissListener(new OnDismissListener() {  
  25.               
  26.             @Override  
  27.             public void onDismiss() {  
  28.                 // popupWindow消失时,设置为全透明  
  29.                 setWindowAlpha(1f);  
  30.             }  
  31.         });  
  32.     }  
  33.   
  34.     /** 
  35.      * 设置屏幕透明度 
  36.      * @param alpha 
  37.      */  
  38.     private void setWindowAlpha(float alpha) {  
  39.         WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();    
  40.         lp.alpha = alpha; //0.0-1.0    
  41.         getActivity().getWindow().setAttributes(lp);  
  42.     }  
  43.       
  44.       
  45.     public int Dp2Dx(Context context, float dp) {  
  46.         final float scale = context.getResources().getDisplayMetrics().density;  
  47.         return (int) (dp * scale + 0.5f);  
  48.     }  

这里就是通过自定义pupupwindow,指定popupwindow的xml布局,这个自己来定,根据父布局来显示popupwindow的位置,当popupwindow显示的时候,设置屏幕为半透明,监听它的消失事件,消失的时候,设置屏幕为全透明效果。最终实现适配魅族手机,这里是小巫想到的一个解决方案,有更好的方法,可以留言交流一下。
http://blog.csdn.net/wwj_748/article/details/44588649
0 0
原创粉丝点击