今天碰到一个bug,点击正在播放的视频时,底下添加的一个布局内的控件都被挤下去了。观察发现,只有这个Layout中的控件被挤下去,而layout本身没有动。排除其他UI show出来挤走的可能。后在该Layout中发现了fitsSystemWindows属性,甚是怀疑,验证后果然是它的问题。点击正在播放的视频时,状态栏show了出来,然后会把带有fitsSystemWindows属性的Layout内控件都往下挤。
下面是其具体说明:
转自:https://blog.csdn.net/liugec/article/details/71437274
fitsSystemWindows属性是我在学习沉浸式模式时候涉及到的一个知识点,因为涉及到Android不同版本间的区别,所以当时也是云里雾里的,所以今天特意整理一下这个属性。
属性说明
fitsSystemWindows属性可以让view根据系统窗口来调整自己的布局;简单点说就是我们在设置应用布局时是否考虑系统窗口布局,这里系统窗口包括系统状态栏、导航栏、输入法等,包括一些手机系统带有的底部虚拟按键。
android:fitsSystemWindows=”true” (触发View的padding属性来给系统窗口留出空间)
这个属性可以给任何view设置,只要设置了这个属性此view的其他所有padding属性失效,同时该属性的生效条件是只有在设置了透明状态栏(StatusBar)或者导航栏(NavigationBar)此属性才会生效。
注意: fitsSystemWindows只作用在Android4.4及以上的系统,因为4.4以下的系统StatusBar没有透明状态。
应用场景
在不同Android版本下,App状态栏和不同版本中系统本身的状态栏的适配;
兼容带有底部虚拟按键的手机系统。
属性使用
1、默认效果
先贴一张未对系统状态栏和导航栏做透明设置时测试布局效果图:
2、系统窗口透明后效果
当设置了透明状态栏(StatusBar)和透明导航栏(NavigationBar)时效果图:
透明状态栏代码设置:
//布局设置
- true
//或者代码设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
透明导航栏代码设置:
//布局设置
- true
//或者代码设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
如果有以上两种情况之一,我们的状态栏(StatusBar)或导航栏(NavigationBar)就会变成透明,并且布局会扩展到StatusBar或NavigationBar的位置。
注意:这里有个关于状态栏和导航栏透明样式的问题,这个是受Android版本决定,4.4以下无透明效果,4.4~5.0是全透明,5.0以上是半透明。我使用的是5.0以上的版本模拟器进行测试的,所以是半透明。
3、设置fitsSystemWindows属性后效果
现在就到了我们关键的fitsSystemWindows属性登场了,只要在根布局中加上android:fitsSystemWindows=”true”效果如下图:
设置了android:fitsSystemWindows=”true”属性后针对透明的状态栏会自动添加一个值等于状态栏高度的paddingTop;针对透明的系统导航栏会自动添加一个值等于导航栏高度的paddingBottom
贴上布局的代码:
附加一个获取状态栏StatusBar的和一个获取导航栏NavigationBar高度的java代码:
//返回值就是状态栏的高度,得到的值单位px
public float getStatusBarHeight() {
float result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimension(resourceId);
}
return result;
}
//返回值就是导航栏的高度,得到的值单位px
public float getNavigationBarHeight() {
float result = 0;
int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimension(resourceId);
}
return result;
}