博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ANDROID-底部虚拟导航的高度获取
阅读量:7029 次
发布时间:2019-06-28

本文共 6817 字,大约阅读时间需要 22 分钟。

ANDROID-底部虚拟导航的高度获取

现在许多手机都引入了虚拟导航,所以在android开发的时候,经常需要对底部的虚拟导航进行适配。这篇文章主要是获取底部导航的高度,以及对导航是否显示进行判断。

如何获取手机底部虚拟导航的高度

本文所使用的方法是在实际项目中使用的,可能并不适合你的要求,所以仅供参考即可。 代码如下

//获取底部导航的高度	 public static int getBottomStatusHeight(Context context) {	            int totalHeight = getDpi(context);	            int contentHeight = getScreenHeight(context);	            PrintLog.printDebug(TAG, "--显示虚拟导航了--");	            return totalHeight - contentHeight;	    } //获取屏幕原始尺寸高度,包括虚拟功能键高度    public static int getDpi(Context context) {        int dpi = 0;        WindowManager windowManager = (WindowManager) 			        context.getSystemService(Context.WINDOW_SERVICE);        Display display = windowManager.getDefaultDisplay();        DisplayMetrics displayMetrics = new DisplayMetrics();        @SuppressWarnings("rawtypes")        Class c;        try {            c = Class.forName("android.view.Display");            @SuppressWarnings("unchecked")            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);            method.invoke(display, displayMetrics);            dpi = displayMetrics.heightPixels;        } catch (Exception e) {            e.printStackTrace();        }        return dpi;    }    //获取屏幕高度 不包含虚拟按键=    public static int getScreenHeight(Context context) {        DisplayMetrics dm = context.getResources().getDisplayMetrics();        return dm.heightPixels;    }复制代码

在大部分手机上,该代码可以正常运行,当虚拟导航栏存在的时候,可以正确的显示底部导航高度,如果底部导航不存在 ,则会显示为0 。既然是在大部分手机上,那么,在部分手机上就是不正确的,比如华为手机。在华为P9上正常使用,后来换了个mate 20,把底部虚拟按键隐藏掉之后,发现页面底部空了一块,而这块的高度正好是虚拟按键的高度,但是此时手机的虚拟按键是隐藏状态,显然,这不是我们需要的结果。因此,如果光判断手机是否支持虚拟按键是不够的,我们还需要知道 当前手机的虚拟按键是否被隐藏了。也就是说:如果手机存在虚拟按键并且显示的情况下,我们才针对页面 和导航进行操作。所以,我们需要先判断一下虚拟导航是否显示 。 判断虚拟导航是否显示,针对华为手机,做了一些的特殊处理 代码如下:

/**     * 判断虚拟导航栏是否显示     *     * @param context 上下文对象     * @return true(显示虚拟导航栏),false(不显示或不支持虚拟导航栏)     */    public static boolean checkNavigationBarShow(@NonNull 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");            //判断是否隐藏了底部虚拟导航            int navigationBarIsMin = 0;            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {                navigationBarIsMin = Settings.System.getInt(context.getContentResolver(),                        "navigationbar_is_min", 0);            } else {                navigationBarIsMin = Settings.Global.getInt(context.getContentResolver(),                        "navigationbar_is_min", 0);            }            if ("1".equals(navBarOverride) || 1 == navigationBarIsMin) {                hasNavigationBar = false;            } else if ("0".equals(navBarOverride)) {                hasNavigationBar = true;            }        } catch (Exception e) {        }        return hasNavigationBar;    }复制代码

本段代码是整理之后的代码,仅供参考。 相信很多人在判断虚拟导航的时候都是使用了

int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { hasNavigationBar = rs.getBoolean(id); } 这段代码来判断的,对于大部分手机来说,基本上是可以实现需求的。但是在华为手机中,紧紧这样还是不够的。因为,我们引入了一个新的参数:navigationbar_is_min ;我们会根据navigationbar_is_min的数值,来判断当前虚拟按键是否显示。该方案通过监控settings数据库表中navigationbar_is_min的值,来判断当前是否显示了虚拟导航。我们可以看到,在代码中加有一个系统版本的判断。这是因为android5.0之后增加了多用户的特性,虚拟键盘的navigationbar_is_min字段从Settings.db的System表格移到了Global表。

因此:最后的获取软键盘高度的方法如下:

/**    * 获取 虚拟按键的高度    *    * @param context    * @return    */   public static int getBottomStatusHeight(Context context) {       if (checkNavigationBarShow(context)) {           int totalHeight = getDpi(context);           int contentHeight = getScreenHeight(context);           PrintLog.printDebug(TAG, "--显示虚拟导航了--");           return totalHeight - contentHeight;       } else {           PrintLog.printDebug(TAG, "--没有虚拟导航 或者虚拟导航隐藏--");           return 0;       }   }复制代码

另外:如果需要对虚拟键盘是否显示进行监听的话,可以使用一下方法

private ContentObserver mNavigationBarObserver = new ContentObserver(new Handler()) {    @Override    public void onChange(boolean selfChange) {        int navigationBarIsMin = 0;        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){            navigationBarIsMin = Settings.System.getInt(getContentResolver(),                        "navigationbar_is_min", 0);        } else {            navigationBarIsMin = Settings.Global.getInt(getContentResolver(),                        "navigationbar_is_min", 0);        }        Log.e(TAG, "onChange: " + navigationBarIsMin);        if (navigationBarIsMin == 1) {            //导航键隐藏了        } else {            //导航键显示了        }    }};复制代码

另外在提供一种方法来判断软键盘是否显示 ,是通过监听页面布局的变化来实现的

FrameLayout content;private boolean mLayoutComplete = false;private int usableHeightPrevious;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    .......    content = (FrameLayout) findViewById(android.R.id.content);    content.post(new Runnable() {        @Override        public void run() {            mLayoutComplete = true;            Log.e(TAG, "content 布局完成");        }    });    content.getViewTreeObserver().addOnGlobalLayoutListener(this);}@Overridepublic void onGlobalLayout() {    if (!mLayoutComplete)        return;    boolean show = isNavigationBarShow(this);}        public static boolean isNavigationBarShow(Activity activity){    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {        Display display = activity.getWindowManager().getDefaultDisplay();        Point size = new Point();        Point realSize = new Point();        display.getSize(size);        display.getRealSize(realSize);        return realSize.y!=size.y;    }else {        boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey();        boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);        if(menu || back) {            return false;        }else {            return true;        }    }}复制代码

至此:获取底部虚拟导航高度的方法已完毕,仅供参考。 //另外,记录一下获取状态栏高度的方法

/**     * 获取状态栏的高度     * @return     */    public static int getStatusBarHeight(Context context) {        try {            Class
c = Class.forName("com.android.internal.R$dimen"); Object obj = c.newInstance(); Field field = c.getField("status_bar_height"); int x = Integer.parseInt(field.get(obj).toString()); return context.getResources().getDimensionPixelSize(x); } catch (Exception e) { e.printStackTrace(); } return 0; }复制代码

以上。

参考文档:

转载于:https://juejin.im/post/5c516ab16fb9a049f1549c93

你可能感兴趣的文章
深海机器人问题
查看>>
正则表达式(括号)、[中括号]、{大括号}的区别小结
查看>>
88.NODE.JS加密模块CRYPTO常用方法介绍
查看>>
java.net.ProtocolException: Exceeded stated content-length of: '13824' bytes
查看>>
asp.net 连接 oracle10g 数据库
查看>>
C 入门 第十一节
查看>>
HTML简单的注册页面搭建
查看>>
【06】Vue 之 组件化开发
查看>>
Docker 安装
查看>>
多数据库数据导入
查看>>
[AVR]高压并行编程---基础知识
查看>>
inl文件介绍
查看>>
前端坑--表单篇
查看>>
P2P原理基础
查看>>
完成登录功能,用session记住用户名
查看>>
DBCP和C3P0使用--未完善
查看>>
JS常用方法(获取Class、获取元素样式、事件监听、cookie、ajax等)
查看>>
BZOJ 1084 最大子矩阵
查看>>
2018杭电多校第三场1007(凸包,极角排序)
查看>>
django中orm的简单操作
查看>>