Android NavigationBar

前言


Android NavigationBar_第1张图片
NavigationBar

上图中黑色区域表示Android设备的虚拟导航栏,早年间的Android设备都还是物理导航栏。随着Android设备的进步(各种搞事情),出现了虚拟导航栏。由于考虑到降低屏占比,又出现了全面屏,可以控制导航栏的开关。

NavigationBar常见操作


  • 获取NavigationBar的高度
  • 判断NavigationBar是否显示
  • 对NavigationBar进行沉浸式处理
  • 修改NavigationBar的UI

如何获取NavigationBar的高度


直接通过资源文件标识符获取,不过需要注意横竖屏情况,因为在部分厂商的设备,横屏和竖屏的NavigationBar高度是有差别的,比如华为横屏情况下NavigationBar的高度就比竖屏情况少了1px

    /**
     * Get Orientation
     *
     * @param context Context
     * @return Overall orientation of the screen.  May be one of portrait(1),landscape(2).
     */
    public static int getOrientation(Context context) {
        Resources resources = context.getResources();
        return resources.getConfiguration().orientation;
    }


    /**
     * Get NavigationBar Height
     */
    public static int getNavigationBarHeight(Context context) {
        Resources resources = context.getResources();
        int resourceId = 0;
        if (getOrientation(context) == 1) {
            //portrait
            resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        } else if (getOrientation(context) == 2) {
            //landscape
            resourceId = resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android");
        }
        if (resourceId > 0) {
            return resources.getDimensionPixelSize(resourceId);
        }
        return 0;
    }

判断NavigationBar是否显示


方法一 (无效)
  • 通过判断设备是否有返回键、菜单键(不是虚拟键,是手机屏幕外的按键)来确定是否有navigation bar
    Android4.0以上所有手机都可以显示NavigationBar,只是手机厂家屏蔽了,所以该方法无效。
      public static boolean checkDeviceHasNavigationBar(Context context) {
            boolean hasMenuKey = ViewConfiguration.get(context)
                    .hasPermanentMenuKey();
            boolean hasBackKey = KeyCharacterMap
                    .deviceHasKey(KeyEvent.KEYCODE_BACK);
            return !hasMenuKey && !hasBackKey;
        }
    
方法二(无效,全面屏会失效)
  • 通过判断设备是否允许显示NavigationBar,和方法一类似,比如全面屏手机肯定是允许显示的,那么在全面屏状态下,实际上没有导航栏显示,但是设备也是返回true,因为允许导航栏显示
    public static boolean checkDeviceHasNavigationBar(Context context) {
          boolean hasNavigationBar = false;
          Resources rs = context.getResources();
          int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
          if (id > 0) {
              hasNavigationBar = rs.getBoolean(id);
          }
          try {
              Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
              Method m = systemPropertiesClass.getMethod("get", String.class);
              String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
              if ("1".equals(navBarOverride)) {
                  hasNavigationBar = false;
              } else if ("0".equals(navBarOverride)) {
                  hasNavigationBar = true;
              }
          } catch (Exception e) {
              hasNavigationBar = false;
          }
          return hasNavigationBar;
      }
    
方法三(刘海屏会失效)
  • 通过比较设备屏幕的实际宽高应用可用屏幕的实际宽高来得出是否有NavigationBar,在刘海屏(凹凸屏)设备会失效
      /**
         * Get Display
         *
         * @param context Context for get WindowManager
         * @return Display
         */
        private static Display getDisplay(Context context) {
            WindowManager wm;
            if (context instanceof Activity) {
                Activity activity = (Activity) context;
                wm = activity.getWindowManager();
            } else {
                wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            }
            if (wm != null) {
                return wm.getDefaultDisplay();
            }
            return null;
        }
      
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        private boolean checkDeviceHasNavigationBar(Context context){
            Display d = getDisplay(context);
            DisplayMetrics realDisplayMetrics = new DisplayMetrics();
            d.getRealMetrics(realDisplayMetrics);
          
            int realHeight = realDisplayMetrics.heightPixels;
            int realWidth = realDisplayMetrics.widthPixels;
          
            DisplayMetrics displayMetrics = new DisplayMetrics();
            d.getMetrics(displayMetrics);
            
            int displayHeight = displayMetrics.heightPixels;
            int displayWidth = displayMetrics.widthPixels;
            
            return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
        }
    
方法四
  • 基本思路:在方法三的基础上除去刘海屏高度的影响,并且在部分厂商设备,可以直接使用厂商提供的方法。目前刘海屏适配已经踩坑,未完待续...
    github代码

参考


Android判断手机时候有导航栏的方法-珊灵之路

你可能感兴趣的:(Android NavigationBar)