Android中的系统栏(状态栏与导航栏)

简介

Android系统中的系统栏可以分为状态栏与导航栏,具体指的如下:


Android中的系统栏(状态栏与导航栏)_第1张图片
官方提供的状态栏的示例图

状态栏:StatusBar

Android中的系统栏(状态栏与导航栏)_第2张图片
官方提供的导航栏示例图

导航栏:NavigationBar

需要注意的是,现在手机为了追求更高的屏幕占比,导航栏物理按键很多都变成了虚拟按键.

正常来讲,应用程序内容区域与系统栏共存,但是显示沉浸式内容的应用程序(如电影或图像)可以暂时调暗系统栏图标,以减少分散注意力的体验,或暂时隐藏条形图以获得完全身临其境的体验。

基础调节系统栏

说明:所谓的调节简单讲就是隐藏显示以及颜色的设置.
系统提供了如下的API来帮助开发者完成奖要求:

View decorView = context.getWindow().getDecorView();
decorView.setSystemUiVisibility( "系统提供的值");
//在你想使用的Activity中调用即可.
其中上述系统提供的值可选项如下:

原图:


Android中的系统栏(状态栏与导航栏)_第3张图片
原图
1

View.SYSTEM_UI_FLAG_LOW_PROFILE
代码

 View db_View = getWindow().getDecorView();
 db_View.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);

解释说明

系统栏进入不引人瞩目的"低调模式"
这适用于游戏,书籍阅读器,视频播放器或任何其他“沉浸式”应用程序,通常的系统被认为太分散注意力。
在低调模式下,状态栏和/或导航图标可能会变暗
另外如何用户手动触摸了状态栏等操作,那么这个标志就会消除了,需要在设置.

效果图:

Android中的系统栏(状态栏与导航栏)_第4张图片
1.png

对比可以看出,将状态栏进行了弱化,但是依旧存在,当用户触摸一下状态栏,那么就会恢复到原图的样式.如果还想要保持这效果,需要重置可以如下:

 @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.

隐藏状态栏与导航栏.
效果如下:


Android中的系统栏(状态栏与导航栏)_第5张图片
2.png

一旦用户触摸状态栏,该标志也会取消,需要在重新设置,采用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使用,结果仍是全屏.(建议配合使用)
Android中的系统栏(状态栏与导航栏)_第6张图片
3.png
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将自动清除,
以便状态栏与导航键两个关键因素重新展示.

效果如下:


Android中的系统栏(状态栏与导航栏)_第7张图片
4.png

将底部的虚拟导航键都给隐藏了.

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,结果仍是全屏.(建议配合使用)

效果如下:


Android中的系统栏(状态栏与导航栏)_第8张图片
5.png
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);

效果图:


Android中的系统栏(状态栏与导航栏)_第9张图片
9.png

类似于修改状态栏与按钮的颜色的效果.一般系统都是两套,一套黑颜色,一套白颜色.这个确定使用深色的,默认是使用白色的.

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及以上

true
设置状态栏半透明,但是并没有设置全透明的主题(如有请留言告诉我)

效果图:


Android中的系统栏(状态栏与导航栏)_第10张图片
结果如图

这样看可能效果不明显,调整布局,设置红色部分高40dp,结果如下:


Android中的系统栏(状态栏与导航栏)_第11张图片
7.png
发现内容区域顶到了上面的状态栏了.可以认为是一种半沉浸式样子.

如果不想这样,可以通过设置

android:fitsSystemWindows= true

这一属性。设置为true让Activity 中setContentView的布局不覆盖状态栏(即相当于给状态栏设置了padding),这个属性要在根布局中使用,如果同时设置了,效果如下:


Android中的系统栏(状态栏与导航栏)_第12张图片
88.png

既然StatusBar由此方法,那么NavigationBar也有类似方法:

        true

效果如下:


Android中的系统栏(状态栏与导航栏)_第13张图片
33.png

发现是灰色的,这是因为内容区域填充到了导航键区域与前面StatusBar类似,如果也添加fitsystemwindow = true


Android中的系统栏(状态栏与导航栏)_第14张图片
54.png

记录修改状态栏颜色例子

        #03A9F4
Android中的系统栏(状态栏与导航栏)_第15张图片
66.png

如果同时和上一部分提到的设置状态栏透明使用效果如何:


Android中的系统栏(状态栏与导航栏)_第16张图片
676.png

发现设置颜色就不管用了,其实很好理解,状态栏设置透明了,还设置颜色有什么用.

在代码中使用 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及以上可以使用

        #03A9F4

效果如下:


Android中的系统栏(状态栏与导航栏)_第17张图片
879.png
代码中动态使用
    //设置导航键颜色也为全透明
            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提供的方法
        true

让状态栏上的字的使用深色.

2 改变导航栏
在23中提供的办法
        true
3 针对于bar与内容区域的细线位置
在27中添加
        #FFC107
在系统导航栏和应用程序内容之间显示指定细线的颜色

上面补充提到的效果展示如下:

        #03A9F4
        #03A9F4
        true
        true
        #FFC107

效果图:在8.1上运行的,可以看到细细的黄线


Android中的系统栏(状态栏与导航栏)_第18张图片
Screenshot_2019-04-08-16-14-48-20.png

响应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.
        }
    }
});

备注:

前面提到的通过主题设置状态栏与导航栏,在标签中有 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);
        }

效果如下:

Android中的系统栏(状态栏与导航栏)_第19张图片
微信截图_20190409112554.png

(2)示例二 通过主题来演示

因为下面的代码是放在value-v23文件夹下,在value或者value-v21文件夹下,需要把不符合版本的哪个属性删除,这里
只是演示:

  

效果图如下:

1556342728(1).jpg

总结感觉已经可以满足日常开发的需要

未完待续,有补充的欢迎留言~

你可能感兴趣的:(Android中的系统栏(状态栏与导航栏))