简介
Android系统中的系统栏可以分为状态栏与导航栏,具体指的如下:
状态栏:StatusBar
导航栏:NavigationBar
需要注意的是,现在手机为了追求更高的屏幕占比,导航栏物理按键很多都变成了虚拟按键.
正常来讲,应用程序内容区域与系统栏共存,但是显示沉浸式内容的应用程序(如电影或图像)可以暂时调暗系统栏图标,以减少分散注意力的体验,或暂时隐藏条形图以获得完全身临其境的体验。
基础调节系统栏
说明:所谓的调节简单讲就是隐藏显示以及颜色的设置.
系统提供了如下的API来帮助开发者完成奖要求:
View decorView = context.getWindow().getDecorView();
decorView.setSystemUiVisibility( "系统提供的值");
//在你想使用的Activity中调用即可.
其中上述系统提供的值可选项如下:
原图:
1
View.SYSTEM_UI_FLAG_LOW_PROFILE
代码
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
解释说明
系统栏进入不引人瞩目的"低调模式"
这适用于游戏,书籍阅读器,视频播放器或任何其他“沉浸式”应用程序,通常的系统被认为太分散注意力。
在低调模式下,状态栏和/或导航图标可能会变暗
另外如何用户手动触摸了状态栏等操作,那么这个标志就会消除了,需要在设置.
效果图:
对比可以看出,将状态栏进行了弱化,但是依旧存在,当用户触摸一下状态栏,那么就会恢复到原图的样式.如果还想要保持这效果,需要重置可以如下:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
//用户下拉状态栏后关闭状态栏回到当前Activity界面上时候
View decorView = getWindow().getDecorView();
int status = SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(status);
}
}
2
View.SYSTEM_UI_FLAG_FULLSCREEN
代码
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
解释如下:
会进入正常的全屏模式,使内容可以覆盖屏幕.但是仍可以允许用户进行交互,比如触摸屏幕顶部,
但是与前面的类似触摸一次此Flag就会清除.
意味着装饰栏(如状态栏)在当前窗口隐藏.
这个属性与android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
* WindowManager.LayoutParams.FLAG_FULLSCREEN 效果一致.
这个修饰符可以覆盖掉ActionBar.
隐藏状态栏与导航栏.
效果如下:
一旦用户触摸状态栏,该标志也会取消,需要在重新设置,采用1里面的方式设置即可.(这样在代码中设置,优先级高)
3
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
代码:
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_FULLSCREEN);
解释如下:
View会按照要求进行布局.
如果没有SYSTEM_UI_FLAG_FULLSCREEN ,依旧允许它在切入和退出该模式时避免伪像(模糊化,像素化,在3.2以上版本,
系统会在320dp x 480dp屏幕上绘制布局,然后将其缩放以填满屏幕,这就会现伪像.),
代价是当它们的一些用户界面在显示时被屏幕装饰(如状态栏)覆盖。
您可以执行内部UI元素的布局,以通过该方法考虑非全屏系统UI.
如果配合SYSTEM_UI_FLAG_FULLSCREEN使用,结果仍是全屏.(建议配合使用)
4
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
代码:
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
解释如下:
正如字面翻译,系统导航栏暂时隐藏.
这是一种比SYSTEM_UI_FLAG_LOW_PROFILE所要求的更为突兀的状态
只支持虚拟按键(Back,Home,the like)设备,会让其消失.
This is useful (in conjunction with the{@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN}
and{@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}window flags)
for displaying content using every last pixel on the display.
有一个限制,导航控件很关键,用户最少的互动将使他们重现,并且当前标志与SYSTEM_UI_FLAG_FULLSCREEN将自动清除,
以便状态栏与导航键两个关键因素重新展示.
效果如下:
将底部的虚拟导航键都给隐藏了.
5
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
代码如下:
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
解释如下:
即使它目前还没有设置SYSTEM_UI_FLAG_HIDE_NAVIGATION
它扔就允许它在切换进入和退出该模式时避免伪像
与SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的作用类似,如何配合SYSTEM_UI_FLAG_HIDE_NAVIGATION,结果仍是全屏.(建议配合使用)
效果如下:
6
SYSTEM_UI_FLAG_LAYOUT_STABLE
保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 使View不会因为System UI的变化而重新layout
7
SYSTEM_UI_FLAG_IMMERSIVE
当使用SYSTEM_UI_FLAG_HIDE_NAVIGATION隐藏导航栏时,View希望保持交互状态。 如果这个标志
未设置,系统会在任何用户交互时强制清除{@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}。
所以这个标志是其专门的修饰符.
8
SYSTEM_UI_FLAG_IMMERSIVE_STICKY
当你使用SYSTEM_UI_FLAG_FULLSCREEN 隐藏栏 and/or 使用SYSTEM_UI_FLAG_HIDE_NAVIAGTION 隐藏导航栏,
额外加上这个标志,可以创建身临其境的体验.
这个标志符只能和这两者或者某个配合使用,才会有效果.
如果没有设置这个标志,那么上面两个标志,在用户触摸顶部状态栏时候会失效
当系统条隐藏在沉浸式模式中时,它们可以通过系统手势暂时显示出来,比如触摸屏幕顶部.会在短暂的时间内恢复.
9
SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
与
SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
请求导航栏以与光导航栏背景兼容的模式绘制。
* For this to take effect, the window must request
* {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
* FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
* {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
* FLAG_TRANSLUCENT_NAVIGATION}.
代码
View db_View = getWindow().getDecorView();
db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
效果图:
类似于修改状态栏与按钮的颜色的效果.一般系统都是两套,一套黑颜色,一套白颜色.这个确定使用深色的,默认是使用白色的.
10
SYSTEM_UI_FLAG_VISIBLE
系统正常默认的系统栏样式
下面记载一些别的办法
记录展示全屏模式的例子
通过设置标志
//启用常规沉浸式模式。
//对于“向后倾斜”模式,删除SYSTEM_UI_FLAG_IMMERSIVE。
//或者“粘性沉浸式”,用SYSTEM_UI_FLAG_IMMERSIVE_STICKY替换它
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
//设置内容显示在系统栏下面,以便
//当系统栏隐藏和显示时,内容不会调整大小。
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //完全体现这三者的"辅助"作用.
//隐藏导航栏和状态栏
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN);
别的方法设全屏
设置主题
android:theme = “@ android:style / Theme.Holo.NoActionBar.Fullscreen” >
4.0以下
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
记录设置状态栏的例子
比较好用的属性,适用于21及以上
<item name="android:windowTranslucentStatus">true</item>
设置状态栏半透明,但是并没有设置全透明的主题(如有请留言告诉我)
效果图:
这样看可能效果不明显,调整布局,设置红色部分高40dp,结果如下:
发现内容区域顶到了上面的状态栏了.可以认为是一种半沉浸式样子.
如果不想这样,可以通过设置
android:fitsSystemWindows= true
这一属性。设置为true让Activity 中setContentView的布局不覆盖状态栏(即相当于给状态栏设置了padding),这个属性要在根布局中使用,如果同时设置了,效果如下:
重要补充:
如果按照上面设置,那么有的手机半透明会有一层灰色的模板,有的手机是完全透明的。如果想完全都是透明,而不是看系统要求。
可以不要上面那些如下设置:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
var dector = window.decorView
dector.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
window.statusBarColor = ColorUtils.blendARGB(Color.TRANSPARENT,Color.WHITE,0.0f)
}
可以实现全透明的沉浸式、原理就是设置状态栏颜色为透明的白色,然后让内容进入到状态栏下面
既然StatusBar由此方法,那么NavigationBar也有类似方法:
<item name="android:windowTranslucentNavigation">true</item>
效果如下:
发现是灰色的,这是因为内容区域填充到了导航键区域与前面StatusBar类似,如果也添加fitsystemwindow = true
记录修改状态栏颜色例子
<item name="android:statusBarColor" tools:ignore="NewApi">#03A9F4</item>
如果同时和上一部分提到的设置状态栏透明使用效果如何:
发现设置颜色就不管用了,其实很好理解,状态栏设置透明了,还设置颜色有什么用.
在代码中使用 context.getWindow().setStatusBarColor(Color.xxxx);
正常使用没事,如果使用
//设置状态栏颜色为全透明
context.getWindow().setStatusBarColor(Color.TRANSPARENT);
那么状态栏哪里一片白,需要配合
{@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
{@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
这两个Flag才可以有效果,后面Demo1就是演示例子.
示例修改导航栏颜色
既然有修改状态栏颜色代码,那么也就有修改导航栏的代码:
21及以上可以使用
<item name="android:navigationBarColor" tools:ignore="NewApi" >#03A9F4</item>
效果如下:
代码中动态使用
//设置导航键颜色也为全透明
context.getWindow().setNavigationBarColor(Color.TRANSPARENT);
但是也需要配合
{@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
{@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
两个Flag来使用.
示例提供的别的方法属性
1 改状态栏上字的颜色
在23提供的方法
<item name="android:windowLightStatusBar" tools:ignore="NewApi">true</item>
让状态栏上的字的使用深色.
2 改变导航栏
在23中提供的办法
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item>
3 针对于bar与内容区域的细线位置
在27中添加
<item name="android:navigationBarDividerColor" tools:ignore="NewApi">#FFC107</item>
在系统导航栏和应用程序内容之间显示指定细线的颜色
上面补充提到的效果展示如下:
<item name="android:statusBarColor" tools:ignore="NewApi">#03A9F4</item>
<item name="android:navigationBarColor" tools:ignore="NewApi" >#03A9F4</item>
<item name="android:windowLightStatusBar" tools:ignore="NewApi">true</item>
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item>
<item name="android:navigationBarDividerColor" tools:ignore="NewApi">#FFC107</item>
效果图:在8.1上运行的,可以看到细细的黄线
响应UI可见性更改(监听)
View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
// Note that system bars will only be "visible" if none of the
// LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// TODO: The system bars are visible. Make any desired
// adjustments to your UI, such as showing the action bar or
// other navigational controls.
} else {
// TODO: The system bars are NOT visible. Make any desired
// adjustments to your UI, such as hiding the action bar or
// other navigational controls.
}
}
});
备注:
前面提到的通过主题设置状态栏与导航栏,在<item>标签中有 tools:ignore="NewApi"
其实在项目中,这部分最好是多写几个value-v21或者value-v23,因为系统是5.0开始提供修改
状态栏颜色的,6.0开始修改状态栏上面文字的颜色的.
总体来讲两种方式,一种是通过主题,一种是通过代码,都可以去完成想要的效果.
Demo时间
(1)示例一:
if (Build.VERSION.SDK_INT >= 21) {
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
//设置状态栏颜色为透明
context.getWindow().setStatusBarColor(Color.TRANSPARENT);
//设置导航键颜色也为透明
context.getWindow().setNavigationBarColor(Color.TRANSPARENT);
} else {
//5.0以下,就单纯的全屏就完了
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
效果如下:
(2)示例二 通过主题来演示
因为下面的代码是放在value-v23文件夹下,在value或者value-v21文件夹下,需要把不符合版本的哪个属性删除,这里
只是演示:
<style name="CarCalculatorTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:statusBarColor">@color/color_wirte</item>
<item name="android:windowLightStatusBar">true</item>
</style>
效果图如下:
(3)实例三 代码动态设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
window.statusBarColor = ColorUtils.blendARGB(Color.TRANSPARENT, Color.WHITE, 0.0f)
}
上述代码也可以完成沉浸式的效果。