问题的起因是我发现 PopupWindow弹出位置不正确时发现的。其实早在两年多前,我就发现我手上的小米MIX2s 获取屏幕高度不正确,后面参考V2EX 的这篇帖子处理了。最近又一次做到类似功能,发现小米、vivo都出现了问题。所以有了今天的内容。
1.回顾过去
说起获取屏幕高度,不知道你是如何理解这个高度范围的?是以应用显示区域高度作为屏幕高度还是手机屏幕的高度。
那么我们先看一下平时使用获取高度的方法
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。也是很直观的方法。