Android学习之沉浸式状态栏

最近做项目的时候,遇到了这个问题,给自己做个笔记。

有时候我们需要某些背景或者自己定义的actionBar,由于状态栏的原因,会显得很突兀,不好看,所以我们需要对状态栏做一些处理

这个需要Android4.4以上的

如果我们不做处理,是这个样子的:
这里写图片描述

感觉很丑,不好看

我们先看一个基础的概念:
这里写图片描述

首先,我们先隐藏状态栏

加入下面这段代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();
    }

效果:

这里写图片描述

但是这种情况,只要我们下拉就可以显示状态栏,但是不会再恢复到之前

在具体实现之前,我们先看看API里面各种Flag的解释:

  • SYSTEM_UI_FLAG_FULLSCREEN
    View has requested to go into the normal fullscreen mode so that its content can take over the screen while still allowing the user to interact with the application.
    View要求全屏模式,所以内容会占据整个屏幕,直到用户对application做出反应

  • SYSTEM_UI_FLAG_HIDE_NAVIGATION
    View has requested that the system navigation be temporarily hidden.
    View要求系统导航暂时被隐藏

  • SYSTEM_UI_FLAG_IMMERSIVE
    View would like to remain interactive when hiding the navigation bar with SYSTEM_UI_FLAG_HIDE_NAVIGATION.
    当设置了SYSTEM_UI_FLAG_HIDE_NAVIGATION的时候同时设置这个,上拉View,导航栏会显示

  • SYSTEM_UI_FLAG_IMMERSIVE_STICKY
    View would like to remain interactive when hiding the status bar with SYSTEM_UI_FLAG_FULLSCREEN and/or hiding the navigation bar with SYSTEM_UI_FLAG_HIDE_NAVIGATION.
    这个和上面的区别是,上面一旦显示了状态栏或者导航栏,就不能恢复全屏,而这个可以

  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    View would like its window to be laid out as if it has requested SYSTEM_UI_FLAG_FULLSCREEN, even if it currently hasn’t.
    这个似乎是View让window就像被要求全屏一样,但是并没有全屏
    (我试了试,状态栏依然看得见)

  • SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    View would like its window to be laid out as if it has requested SYSTEM_UI_FLAG_HIDE_NAVIGATION, even if it currently hasn’t.

  • SYSTEM_UI_FLAG_LAYOUT_STABLE
    When using other layout flags, we would like a stable view of the content insets given to fitSystemWindows(Rect).
    当使用layout有关的flag的时候,对fitSystemWindows(Rect)提供的布局提供稳定

当我将UI的flag改为这个的时候:

decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                |View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

然后在布局中的ImagView中:

 <ImageView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:src="@drawable/bg_1"
       android:scaleType="centerCrop"
       android:fitsSystemWindows="true"
       />

得到的效果:
这里写图片描述

如果在ImageView的根布局设置android:fitsSystemWindows="true"
得到的是:

这里写图片描述

如果我将 android:fitsSystemWindows=”false”或者就不设置它,得到的就是含有状态栏和导航栏的全屏

  • SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
    Requests the status bar to draw in a mode that is compatible with light status bar backgrounds.
    这个API要求在23以上

  • SYSTEM_UI_FLAG_LOW_PROFILE
    View has requested the system UI to enter an unobtrusive “low profile” mode
    就是隐藏状态栏上的一些东西,只剩下电池和时间

  • SYSTEM_UI_FLAG_VISIBLE
    View has requested the system UI (status bar) to be visible (the default).
    默认的,都可见

  • SYSTEM_UI_LAYOUT_FLAGS
    Flags that can impact the layout in relation to system UI.
    可以影响到系统UI的布局的标志

透明状态栏

我们来看代码:

if(Build.VERSION.SDK_INT >= 21){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            |View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
             getWindow().setNavigationBarColor(Color.TRANSPARENT);
        }

        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();

这个需要API 21以上的,所以我们需要加个判断

效果:
这里写图片描述

感觉上美多了
这样我们就更能理解前面的那两个flag了,它是让主体内容占据全屏,但是我们任然能看到状态栏和导航栏,但是如果将状态栏和导航栏的颜色变为透明,我们就能看到全部的主体内容了

真正的沉浸式:
 if(Build.VERSION.SDK_INT >= 19){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            |View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            |View.SYSTEM_UI_FLAG_FULLSCREEN
                            |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            |View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

效果:
这里写图片描述

我们看到上面我们对状态栏和导航栏设置透明是直接用的:getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().setNavigationBarColor(Color.TRANSPARENT);

这是是API 21以上才能用,也就是支持Android5.0以上,因此我们要兼容4.4怎么办呢:
我们会使用到Window中的setFlags()方法:

Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){

            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);


        }

这里,我使用的是toolbar
效果:
这里写图片描述

这个用的模拟器是android4.4,API 19的
如果我用android5.0 API 21
这里写图片描述

我们可以看到4.4的状态栏是透明的,而5.0的状态栏是半透明的
记得在toolbar中加一个android:fitsSystemWindows="true"

它的作用是什么呢:
官方描述:Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.
简单描述:
这个一个boolean值的内部属性,让view可以根据系统窗口(如status bar)来调整自己的布局,如果值为true,就会调整view的paingding属性来给system windows留出空间
实际效果:
当status bar为透明或半透明时(4.4以上),系统会设置view的paddingTop值为一个适合的值(status bar的高度)让view的内容不被上拉到状态栏,当在不占据status bar的情况下(4.4以下)会设置paddingTop值为0(因为没有占据status bar所以不用留出空间)。

如果我想4.4和5.0兼容,我是这样做的:

 if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            |View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            );

            window.setStatusBarColor(Color.TRANSPARENT);
            window.setNavigationBarColor(Color.TRANSPARENT);
        }else  if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            ,WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }

这样状态栏就不会半透明了

注意一点,合理使用fitSystemWindows

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值