资深架构师:深入聊聊获取屏幕高度这件事

回顾过去说起获取屏幕高度,不知道你是如何理解这个高度范围的?是以应用显示区域高度作为屏幕高度还是手机屏幕的高度 。
那么我们先看一下平时使用获取高度的方法:
public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();DisplayMetrics dm = new DisplayMetrics();display.getMetrics(dm);return dm.heightPixels;}//或public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Point point = new Point();wm.getDefaultDisplay().getSize(point);return point.y;}// 或public static int getScreenHeight(Context context) {return context.getResources().getDisplayMetrics().heightPixels;}// 貌似还有更多的方法以上三种效果一致,只是写法略有不同 。
当然你或许使用的是这种:
public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();DisplayMetrics dm = new DisplayMetrics();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {display.getRealMetrics(dm);} else {display.getMetrics(dm);}return dm.heightPixels;}// 其他几种写法大同小异...这个方法判断了系统大于等于Android 4.2时,使用getRealMetrics(getRealSize)来获取屏幕高度 。那么这里发生了什么,为什么会这样?
其实在Andoird 4.0时,引入了虚拟导航键,如果你继续使用getMetrics之类的方式,获取的高度是去除了导航栏的高度的 。
当时因为在4.0和4.2之间还没有的getRealMetrics这个方法,所以甚至需要添加下面的适配代码:
try {heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);} catch (Exception e) {}现在不会还有人适配4.4甚至5.0一下的机子了吧,不会吧不会吧 。。。所以历史的包袱可以去掉了 。

资深架构师:深入聊聊获取屏幕高度这件事

文章插图
 
上面方法名都是getScreenHeight,可是这个高度范围到底和你需要的是否一致 。这个需要开发时注意,我的习惯是ScreenHeight对应用显示的高度,不包括导航栏(非全屏下),RealHeight来指包含导航栏和状态栏的高度(getRealMetrics) 。
PS:以前也使用过AndroidUtilCode这个工具库,里面将前者方法名定义为getAppScreenHeight,后者为getScreenHeight 。也是很直观的方法 。
下文中我会以自己的习惯,使用ScreenHeight和RealHeight来代表两者 。
我印象中华为手机很早就使用了虚拟导航键,如下图(图片来源):
资深架构师:深入聊聊获取屏幕高度这件事

文章插图
 
比较特别的是,当时华为的导航栏还可以显示隐藏,注意图中左下角的箭头 。点击可以隐藏,上滑可以显示 。即使这样,使用getScreenHeight也可以准确获取高度,隐藏了ScreenHeight就等于RealHeight 。
上述的这一切在“全面屏”时代没有到来之前,没有什么问题 。
立足当下 
小米MIX的发布开启了全面屏时代(16年底),以前的手机都是16:9的,记得雷布斯在发布会上说过,他们费了很大的力气说服了谷歌去除了16:9的限制(从Android 7.0开始)
资深架构师:深入聊聊获取屏幕高度这件事

文章插图
 

资深架构师:深入聊聊获取屏幕高度这件事

文章插图
 
【资深架构师:深入聊聊获取屏幕高度这件事】全面屏手机是真的香,不过随之也带来适配问题 。首当其冲的就是刘海屏,各家有各自的获取刘海区域大小的方法 。主要原因还是国内竞争的激烈,各家为了抢占市场,先于谷歌定制了自己的方案 。这一点让人想起了万恶的动态权限适配 。。。
其实在刘海屏之下,还隐藏一个导航栏的显示问题,也就是本篇的重点 。全面屏追求更多的显示区域,随之带来了手势操作 。在手势操作模式下,导航栏是隐藏状态 。
本想着可以和上面提到的华为一样,隐藏获取的就是RealHeight,显示就是减去导航栏高度的ScreenHeight 。然而现实并不是这样,下表是我收集的一些全面屏手机各高度的数据 。
资深架构师:深入聊聊获取屏幕高度这件事

文章插图
 
ScreenHeight一栏中括号内表示显示导航栏时获取的屏幕高度 。
大致的规律总结如下: