关于状态栏的讨论不少,咱们今天从需求的角度来看一下对于状态栏的知识点:php
(4.4)
Window
DecorView
(4.4)
:windowTranslucentStatus
,须要解决重叠问题
padding
fitsSystemWindows
(5.0)
:
colorPrimaryDark
,style
中指定。setStatusBarColor
,动态设定。(4.4)
:
SYSTEM_UI_FLAG_VISIBLE
:状态栏不覆盖根布局SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
:状态栏覆盖根布局(5.0)
(6.0)
不显示状态栏通常用于屏幕可显示区域较小的时候,而且要求可见面积较大的状况,例如视频、横屏等,而不显示状态栏的方法有两种,下面咱们分别介绍一下:html
Activity
所属的Window
public static void setStatusBarVisibleByWindow(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
if (visible) {
winParams.flags &= ~bits;
} else {
winParams.flags |= bits;
}
window.setAttributes(winParams);
}
}
复制代码
DecorView
public static void setStatusBarVisibleByDecorView(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
if (visible) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
}
复制代码
##2.3 小结 这两种方法不能够混合使用,也就是说,不能经过其中一种方法将状态栏隐藏,又利用另外一种方法将它显示出来。android
在显示状态栏的状况下,咱们将需求分为如下三类:bash
要求安卓版本大于4.4。 咱们能够在style
中指定,而后设置给Activity
或者Application
:布局
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
复制代码
固然,也能够经过代码来指定:ui
public static void setStatusBarTransparent(Activity activity) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
winParams.flags |= bits;
window.setAttributes(winParams);
}
}
复制代码
解决状态栏透明时和根布局重叠的问题 这两种方法是等效的,可是它们都存在一个问题,根布局会和状态栏重叠,这时候就有两种解决办法:spa
padding
这种方法有一点很差,就是咱们须要事先知道状态栏的高度是多少,或者动态地获取,并动态设置padding
。code
fitsSystemWindows
为了解决上面的状况,咱们能够经过fitsSystemWindows
属性让系统自动根据状态栏的高度来给咱们的布局留下足够的空间。视频
xml
中配置android:fitsSystemWindows
属性:<LinearLayout android:fitsSystemWindows="true">
复制代码
须要注意,使用上面的方法来试状态栏透明,须要在Activity
的onCreate
以前设置,若是在以后设置,那么可能会出现意料以外的结果,若是想要在代码当中设置状态栏透明,那么建议采用3.2
和3.3
的结合版本,也就是改变状态栏颜色为透明 + 改变布局,咱们分析完下面的两种以后,再看一下怎么在代码中设置。xml
在状态栏不透明的状况下,咱们能够经过下面的方法来改变状态栏的颜色,要求Android
版本大于5.0
:
style
设置其中colorPrimaryDark
就是指定的状态栏颜色
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@android:color/holo_green_light</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
复制代码
这里有一点:若是咱们设置了上面的属性,而且设置了windowTranslucentStatus
,即便不将fitSystemWindow
设为true
,也不会使状态栏和根布局重叠。
public static void setStatusBarColor(Activity activity, int colorId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorId));
}
}
}
复制代码
因为上面讨论的两种方法都只能在5.0
以上实现,所以若是咱们但愿在5.0
如下动态改变状态栏的颜色,那么就只能经过3.1
中的方法,把状态栏设置为透明,而后在布局中添加一个和状态栏高度相同的背景,经过动态改变这个背景的颜色,来实现状态栏颜色的改变。
其实在上面的两种方法中,咱们也间接地改变了状态栏和根布局的关系,固然,咱们也能够单纯改变布局关系,而不对状态栏做出任何改变:
public static void setStatusBarOverlay(Activity activity, boolean overlay) {
Window window = activity.getWindow();
if (window != null) {
if (overlay) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
}
复制代码
因为这种方式结合了3.2
和3.3
,所以要求版本要大于5.0
:
public static void setStatusBarTransparentDynamic(Activity activity, boolean overlay) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (!overlay) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
window.setStatusBarColor(Color.TRANSPARENT);
}
}
}
复制代码
这种方法要求Android
的API
大于6.0
:
public static void setStatusBarItemColor(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Window window = activity.getWindow();
if (window != null) {
final int bits = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
int currentBits = window.getDecorView().getSystemUiVisibility();
if (dark) {
currentBits |= bits;
} else {
currentBits &= ~bits;
}
window.getDecorView().setSystemUiVisibility(currentBits);
}
}
}
复制代码
总结下来,在显示状态栏的状况下,适配范围最广的是下面这种方法:
DecorView
设置成透明而且重叠的模式(如3.4
)6.0
或者厂商的方法。对于状态栏的操做主要是两种:一种是对DecorView
操做,另外一种是对window
操做,使用的时候对除了设置状态栏颜色外的操做必定要保持统一,必定不要同时进行这两种方法来进行相反的操做。举个例子,若是采用了3.1
中的对window
进行操做使得状态栏透明,并经过fitSystemWindows
改变布局,那么就不要再采用3.3
中DecorView.setSystemUiVisibility()
的方式来改变布局的结构,最好是成对地出现,不然会使得布局出现意料以外的状况。
最后附上代码:
public class StatusBarUtils {
public static void setStatusBarVisibleByWindow(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
if (visible) {
winParams.flags &= ~bits;
} else {
winParams.flags |= bits;
}
window.setAttributes(winParams);
}
}
public static void setStatusBarVisibleByDecorView(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
if (visible) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
}
public static void setStatusBarTransparent(Activity activity) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
winParams.flags |= bits;
window.setAttributes(winParams);
}
}
public static void setStatusBarTransparentDynamic(Activity activity, boolean overlay, boolean transparent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
if (transparent) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (!overlay) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
window.setStatusBarColor(Color.TRANSPARENT);
}
}
}
}
public static void setStatusBarBackgroundColor(Activity activity, int colorId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorId));
}
}
}
public static void setStatusBarOverlay(Activity activity, boolean overlay) {
Window window = activity.getWindow();
if (window != null) {
if (overlay) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
}
public static void setStatusBarItemColor(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Window window = activity.getWindow();
if (window != null) {
final int bits = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
int currentBits = window.getDecorView().getSystemUiVisibility();
if (dark) {
currentBits |= bits;
} else {
currentBits &= ~bits;
}
window.getDecorView().setSystemUiVisibility(currentBits);
}
}
}
}
复制代码