前言
目前,android屏幕上大致分成三个部分:通知栏,内容区、虚拟导航栏(NavigatorBar) 因为这三个区域引起的问题数不胜数,必须好好总结一下
一般情况下,三个区域都显示。如果应用设置了全屏,比如:
requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 复制代码
当然也可以直接设置application的样式为全屏。这时候通知栏隐藏,内容区向上扩展。
如果在系统设置中开启的虚拟手势,虚拟导航栏就隐藏了。这时候内容区就向下扩展。如果同时满足这两个条件,内容区域就实现了真正意义上的全屏。
rootView和contentView
我们知道activity的view树最顶层是rootView,它是一个DocerView,可以通过view.getRootView()
或getWindow().getDecorView()
获取。
那么它的区域是多少?
一般我们理解它的区域就是内容区域,但是这是错误的。它的区域是内容区+虚拟导航栏。
这里就需要区别一下contentView
,contentView
是指android.R.id.content
对应的view,通过findViewById(android.R.id.content)
获取。这个才是真正的内容区。
所以rootView = contentView + NavigatorBar
所以当全屏隐藏通知栏时,rootView就是屏幕大小。当NavigatorBar隐藏时,contentView等于rootView的大小。
通知栏高度
我们经常会想用到通知栏高度,但是android并没有提供这个api,那么怎么办?
想想我们需要用到这一高度的时候一定是通知栏显示的时候,这时候rootView.top就是通知栏高度。
这样就很容易获取到通知栏高度
heightPixels
注意:横屏则是widthPixels
因为竖屏是虚拟导航栏在下面,所以会影响到heightPixels的取值。Android中有几个heightPixels,他们有什么关系
先来看看有哪几种方式获取heightPixels
1、
getResources().getDisplayMetrics().heightPixels 复制代码
2、
var windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager var metrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(metrics) var height = metrics.heightPixels 复制代码
3、
var windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager var metrics = DisplayMetrics() windowManager.defaultDisplay.getRealMetrics(metrics) var height = metrics.heightPixels 复制代码
首先,第一种和第二种方式获取的是同样的东西,只是不同的方法而已,我们称它为rawHeight
第三种获取的明显不同,称为realHeight
那么rawHeight
和realHeight
有什么区别?
它们两个都是屏幕高度,区别在于是否包含虚拟导航栏。rawHeight
不包含NavigatorBar高度,而realHeight
则包含。
注意两个都包含通知栏高度,所以它们两与rootView.height都不一样,同样与contentView.height也不一样。
对比
上面提到了很多高度,包括两个屏幕高度(rawHeight,realHeight),两个窗口高度(rootView.height,contentView.height)和两个边栏高度(通知栏和虚拟导航栏)
其中知道了rawHeight
和realHeight
,虚拟导航栏高度就可以很容易得到,即realHeight - rawHeight
。
那么这些高度存在怎样的关系?
首先上面知道rootView = contentView + NavigatorBar,但是如果NavigatorBar隐藏,rootView和contentView就一样高。
但是rawHeight,realHeight不同,即使NavigatorBar隐藏,rawHeight也等于realHeight-NavigatorBar
当NavigatorBar隐藏时,realHeight = rootView + 通知栏,这种情况再全屏时,realHeight和rootView就相等了(也等于contentView)
而当NavigatorBar显示的时候,rawHeight = rootView + 通知栏, realHeight = rootView + 通知栏 + NavigatorBar
目前官方没有判断虚拟导航栏显示隐藏的api,网上的都不是完全之法。其实可以通过比较rootView和contentView的bottom来判断。
显示区域(键盘高度)
还有一种区域,就是实际显示区域,可以通过
var rect = Rect() view.getWindowVisibleDisplayFrame(rect) 复制代码
获得,这个就是真正显示的区域,比如键盘弹出时,通过rootView获取的这个rect的高度与实际高度不一致,这样就可以判断出键盘的显示和隐藏。
但是如果想得到键盘高度,用rootView不行,因为它包含虚拟导航栏,如果用实际高度-显示高度,在虚拟键盘隐藏时得到的高度要大与键盘高度。
这时候使用contentView获取即可,因为它不包含虚拟导航栏。