最近在做一个项目,绘制一个自定义View,距离屏幕底部 XXdp,在占满全屏的父布局里的 onLayout() 回调方法中对该自定义 View 进行位置布局,Y 轴的坐标算法如下:
val mViewYPosition = Utils.getScreenHeight() - mView.measureHeight - bottomMargin
其中获取手机屏幕高度的工具方法如下:
private int sScreenHeight = 0
public static int getScreenHeight() {
if (sScreenHeight != 0) {
return sScreenHeight;
}
WindowManager wm = (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE);
if (wm != null && wm.getDefaultDisplay() != null) {
DisplayMetrics outMetrics = new DisplayMetrics();
Display display = wm.getDefaultDisplay();
display.getMetrics(outMetrics);
switch (display.getRotation()) {
case Surface.ROTATION_0:
case Surface.ROTATION_180://fall through
sScreenHeight = outMetrics.heightPixels;
sScreenWidth = outMetrics.widthPixels;
break;
case Surface.ROTATION_90:
case Surface.ROTATION_270://fall through
sScreenHeight = outMetrics.widthPixels;
sScreenWidth = outMetrics.heightPixels;
break;
}
return sScreenHeight;
} else {
return 1080;
}
}
实际测试发现,在不同安卓机型上该自定义 View 距离底部的高度是明显不一致的。
最后通过排查发现,不同机型的屏幕高度获取方式是不一样的:
- 比如在小米 note3(Android 9, 物理导航栏) 这种机型,screenHeight 就是最终的屏幕高度
- 而小米10的最终屏幕高度是 screenHeight + statusBarHeight + navigationBarHeight
这里关于手机屏幕尺寸的发展史可以看这篇文章,写得很详细 《聊聊获取屏幕高度这件事》。
厂商从未停止魔改的步伐,如果每次出新尺寸的屏幕都要去适配一下,是很费力的。
因此,最佳做法是直接获取当前这个全屏父布局的高度,来间接得到准确的 ScreenHeight。
以下列出错误方式和准确方式:
- 错误方式
var totalScreenHeight = DeviceTool.getStatusBarHeight() + DeviceTool.getScreenHeight()
+ DeviceTool.getNavigationBarHeight() //错误方式
- 以不变应万变的解决方案
var totalScreenHeight = parentView.measuredHeight //正确方式(注意获取measureHeight 的时机,此处只是示例)
另外,这里提供一种查看屏幕分辨率的快捷命令:
adb shell wm size
打印如下: