navigationbar展示位置的获取

概述: 之前项目中曾经做过一个功能,需要根据在页面顶部靠边的位置添加一个菜单按钮,按钮点击后弹出popwindow,如果设备显示导航栏navigationbar,当导航栏显示在底部的时候,菜单键显示在页面左上角,当导航栏不在底部,而是在左右两侧的时候,菜单键总是显示在导航栏的对侧。

解决思路: 当进入页面的是,需要在页面的oncreate中根据导航栏的位置来设置菜单键的位置,经过查找,好像没有开放API可以返回导航栏的位置,网络搜索,也没有找到相关的信息,只剩下最后一个方法,去源码里头找找看看有没有类似的实现。查找思路如下:

  1. 在/framework/base/core/res/values文件夹中搜索navigation字符
  2. 如果步骤1搜索到了一些可能有用的信息,则根据步骤1搜索得到的可能信息去java代码中搜索
  3. 如果步骤1中没有没有得到可能有用的信息,则根据经验去systemui文件夹下或者几个跟窗口管理较密切的类中去查找,比如:windowmanagerservice,PhoneWindowManager等中去继续查找相关字符
实现过程: 1.在values文件夹中搜索navigation字符,得到的信息较多,需要自己去一个个筛选哪些信息可能会有用,这里发现很多都是导航栏高度、和颜色设置,这里发现一个是否显示导航栏的设置,在config.xml中:
false

【navigationbar展示位置的获取】2.觉得这个设置可能引出我需要的信息,所以继续在java代码中去查找:
首先在framework/base/core/java/路径下查找config_showNavigationBar,结果没有找到任何相关引用的。
然后继续在frameworks/base/services/core/java目录下查找,结果在PhoneWindowManager类中找到了相关的引用:
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);

继续根据这个变量进行查找,发现该类中针对导航栏的方法较多,但是还是没有找到我们需要的信息,更换搜索词,扩大搜索范围,搜索navigation,最终发现有如下隐藏方法:
private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { if (mNavigationBarCanMove && displayWidth > displayHeight) { if (displayRotation == Surface.ROTATION_270) { return NAV_BAR_LEFT; } else { return NAV_BAR_RIGHT; } } return NAV_BAR_BOTTOM; }

至此,我们就已经得到了我们所需要的全部信息了,方法虽然是hide方法,但是实现较为简单,我们可以将其实现方法直接拿出来使用即可,经过修饰与兼容android不同版本之后得出如下方法:
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); } return hasNavigationBar; }/** 8.0及以下系统获取导航栏显示位置 *返回导航栏位置,1是显示在底部,2是显示在右侧,0是不显示 * @param cn * @return */ public static int getNavPosO(Context cn) { WindowManager wmg = (WindowManager)cn.getSystemService(Context.WINDOW_SERVICE); final Display display = wmg.getDefaultDisplay(); DisplayMetrics metricsReal = new DisplayMetrics(); display.getRealMetrics(metricsReal); DisplayMetrics metricsCurrent = new DisplayMetrics(); wmg.getDefaultDisplay().getMetrics(metricsCurrent); int currH = metricsCurrent.heightPixels; int currW = metricsCurrent.widthPixels; int realW = metricsReal.widthPixels; int realH = metricsReal.heightPixels; if(currH != realH && currW == realW) { return 1; } else if(currW != realW && currH == realH) { return 2; } else { return 0; }}/**9.0获取导航栏显示位置,1左边,2右边,4底部 * * @param context * @return */ public static int getNavPosP(Context context) { WindowManager wmg = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); int pos = 0; Display display = wmg.getDefaultDisplay(); int rotate = display.getRotation(); int height = display.getHeight(); int width = display.getWidth(); if (width > height) { if (rotate == Surface.ROTATION_270) { pos =1; //left } else { pos = 2; //right } } else { pos = 4; //bottom } return pos; }

    推荐阅读