android4.4以上沉浸式状态栏和导航栏实现以及Bar的其他管理

自从android4.4开始,android手机状态栏再也不是一成黑的时代,之前叫做变色龙,miui6发布会把他叫做沉浸式,之后大家就自然而然的接受了沉浸式这个名称,其实实际应该叫做Translucent Bar,即为透明状态栏。
  沉浸式实现原理其实是使整个activity布局延伸到整个屏幕,然后使状态栏变成透明色,有些手机会有导航栏,同样也可以把导航栏变成透明色,这样会使一些app更加美观。

先看两个概念

  • 状态栏


    状态栏.png
  • 导航栏


    导航栏.png

废话不多说了,直接看GIF

[图片上传失败...(image-5471b1-1534838763494)]

1、引入

github仓库地址:https://github.com/gyf-dev/ImmersionBar

logo.png
  • android studio
     // 基础依赖包,必须要依赖
     implementation 'com.geyifeng.immersionbar:immersionbar:3.2.1'
     // kotlin扩展(可选)
     implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.1'
     // fragment快速实现(可选)
     implementation 'com.geyifeng.immersionbar:immersionbar-components:3.2.1'
    
    

关于全面屏与刘海

关于全面屏

在manifest加入如下配置,四选其一,或者都写

① 在manifest的Application节点下加入

   <meta-data 
     android:name="android.max_aspect"
     android:value="2.4" />

② 在manifest的Application节点中加入

   android:resizeableActivity="true"

③ 在manifest的Application节点中加入

   android:maxAspectRatio="2.4"

④ 升级targetSdkVersion为25以上版本

关于刘海屏

在manifest的Application节点下加入,vivo和oppo没有找到相关配置信息

   <!--适配华为(huawei)刘海屏-->
   <meta-data 
     android:name="android.notch_support" 
     android:value="true"/>
   <!--适配小米(xiaomi)刘海屏-->
   <meta-data
     android:name="notch.config"
     android:value="portrait|landscape" />

2、特性

1)基本介绍

  • 基础用法
    ImmersionBar.with(this).init();
  • 高级用法,如果基础用法不能满足你的需求,可以试试这里的方法
       ImmersionBar.with(this)
                 .transparentStatusBar()  //透明状态栏,不写默认透明色
                 .transparentNavigationBar()  //透明导航栏,不写默认黑色(设置此方法,fullScreen()方法自动为true)
                 .transparentBar()             //透明状态栏和导航栏,不写默认状态栏为透明色,导航栏为黑色(设置此方法,fullScreen()方法自动为true)
                 .statusBarColor(R.color.colorPrimary)     //状态栏颜色,不写默认透明色
                 .navigationBarColor(R.color.colorPrimary) //导航栏颜色,不写默认黑色
                 .barColor(R.color.colorPrimary)  //同时自定义状态栏和导航栏颜色,不写默认状态栏为透明色,导航栏为黑色
                 .statusBarAlpha(0.3f)  //状态栏透明度,不写默认0.0f
                 .navigationBarAlpha(0.4f)  //导航栏透明度,不写默认0.0F
                 .barAlpha(0.3f)  //状态栏和导航栏透明度,不写默认0.0f
                 .statusBarDarkFont(true)   //状态栏字体是深色,不写默认为亮色
                 .navigationBarDarkIcon(true) //导航栏图标是深色,不写默认为亮色
                 .autoDarkModeEnable(true) //自动状态栏字体和导航栏图标变色,必须指定状态栏颜色和导航栏颜色才可以自动变色哦
                 .autoStatusBarDarkModeEnable(true,0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                 .autoNavigationBarDarkModeEnable(true,0.2f) //自动导航栏图标变色,必须指定导航栏颜色才可以自动变色哦
                 .flymeOSStatusBarFontColor(R.color.btn3)  //修改flyme OS状态栏字体颜色
                 .fullScreen(true)      //有导航栏的情况下,activity全屏显示,也就是activity最下面被导航栏覆盖,不写默认非全屏
                 .hideBar(BarHide.FLAG_HIDE_BAR)  //隐藏状态栏或导航栏或两者,不写默认不隐藏
                 .addViewSupportTransformColor(toolbar)  //设置支持view变色,可以添加多个view,不指定颜色,默认和状态栏同色,还有两个重载方法
                 .titleBar(view)    //解决状态栏和布局重叠问题,任选其一
                 .titleBarMarginTop(view)     //解决状态栏和布局重叠问题,任选其一
                 .statusBarView(view)  //解决状态栏和布局重叠问题,任选其一
                 .fitsSystemWindows(true)    //解决状态栏和布局重叠问题,任选其一,默认为false,当为true时一定要指定statusBarColor(),不然状态栏为透明色,还有一些重载方法
                 .supportActionBar(true) //支持ActionBar使用
                 .statusBarColorTransform(R.color.orange)  //状态栏变色后的颜色
                 .navigationBarColorTransform(R.color.orange) //导航栏变色后的颜色
                 .barColorTransform(R.color.orange)  //状态栏和导航栏变色后的颜色
                 .removeSupportView(toolbar)  //移除指定view支持
                 .removeSupportAllView() //移除全部view支持
                 .navigationBarEnable(true)   //是否可以修改导航栏颜色,默认为true
                 .navigationBarWithKitkatEnable(true)  //是否可以修改安卓4.4和emui3.x手机导航栏颜色,默认为true
                 .navigationBarWithEMUI3Enable(true) //是否可以修改emui3.x手机导航栏颜色,默认为true
                 .keyboardEnable(true)  //解决软键盘与底部输入框冲突问题,默认为false,还有一个重载方法,可以指定软键盘mode
                 .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)  //单独指定软键盘模式
                 .setOnKeyboardListener(new OnKeyboardListener() {    //软键盘监听回调,keyboardEnable为true才会回调此方法
                       @Override
                       public void onKeyboardChange(boolean isPopup, int keyboardHeight) {
                           LogUtils.e(isPopup);  //isPopup为true,软键盘弹出,为false,软键盘关闭
                       }
                  })
                 .setOnNavigationBarListener(onNavigationBarListener) //导航栏显示隐藏监听,目前只支持华为和小米手机
                 .setOnBarListener(OnBarListener) //第一次调用和横竖屏切换都会触发,可以用来做刘海屏遮挡布局控件的问题
                 .addTag("tag")  //给以上设置的参数打标记
                 .getTag("tag")  //根据tag获得沉浸式参数
                 .reset()  //重置所以沉浸式参数
                 .init();  //必须调用方可应用以上所配置的参数

2)详细介绍

  • 解决状态栏和布局顶部重合

上面已经说了,沉浸式原理就是使整个布局延伸到状态栏和导航栏,既然这样必然导致一个问题,就是状态栏和布局顶部重叠,直接看图

状态栏和布局顶部重叠.png

眼神好的同学已经看到上图中给了五种解决方案啦,在这里说一下

  • 1 使用dimen自定义状态栏高度

    • 在values-v19/dimens.xml文件下
        <dimen name="status_bar_height">25dp</dimen>
    
    • 在values/dimens.xml文件下
        <dimen name="status_bar_height">0dp</dimen>
    
    • 然后在布局界面添加view标签,高度指定为status_bar_height
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:app="http://schemas.android.com/apk/res-auto"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:background="@color/darker_gray"
           android:orientation="vertical">
       
           <View
               android:layout_width="match_parent"
               android:layout_height="@dimen/status_bar_height"
               android:background="@color/colorPrimary" />
       
           <android.support.v7.widget.Toolbar
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:background="@color/colorPrimary"
               app:title="方法一"
               app:titleTextColor="@android:color/white" />
       </LinearLayout>
    
  • 2 使用系统的fitsSystemWindows属性

    • 在布局文件的根节点使用android:fitsSystemWindows="true"属性
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:fitsSystemWindows="true">
        </LinearLayout>
    
    • 然后使用ImmersionBar时候必须指定状态栏颜色
        ImmersionBar.with(this)
             .statusBarColor(R.color.colorPrimary)
             .init();
    
  • 3 使用ImmersionBar的fitsSystemWindows(boolean fits)方法
  • 实现原理是获得rootView的根节点,然后设置距离顶部的padding值为状态栏的高度值
```java
    ImmersionBar.with(this)
        .statusBarColor(R.color.colorPrimary)
        .fitsSystemWindows(true)  //使用该属性必须指定状态栏的颜色,不然状态栏透明,很难看
        .init();
```
  • 4 使用ImmersionBar的statusBarView(View view)方法

    • 在标题栏的上方增加View标签(也可以为其他标签),高度指定为0dp
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               xmlns:app="http://schemas.android.com/apk/res-auto"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:background="@color/darker_gray"
               android:orientation="vertical">
           
               <View
                   android:layout_width="match_parent"
                   android:layout_height="0dp"
                   android:background="@color/colorPrimary" />
           
               <android.support.v7.widget.Toolbar
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:background="@color/colorPrimary"
                   app:title="方法四"
                   app:titleTextColor="@android:color/white" />
        </LinearLayout>
    
    • 然后使用ImmersionBar的statusBarView方法,指定view就可以啦,实现原理:ImmersionBar获取状态栏的高度,传入view,设置高度为获取到的状态栏高度
         ImmersionBar.with(this)
               .statusBarView(view)
               .init();
    
  • 5 使用ImmersionBar的titleBar(View view)方法

        ImmersionBar.with(this)
                  .titleBar(view) //指定标题栏view
                  .init();
  • 总结:这五种方法,任选其一使用就可以了,不要一起使用哦,根据项目而定,比如有侧边栏的,建议使用第1种或者第4种或者第5种,最后来一张效果图


    五种方法最后效果图.jpg
  • 在Fragment中实现沉浸式

在Fragment使用ImmersionBar

SimpleImmersionFragmentImmersionFragment区别是什么?

方法名字 SimpleImmersionFragment ImmersionFragment
initImmersionBar():沉浸式代码写着这里
immersionBarEnabled():当前Fragment是否可以走initImmersionBar方法
onLazyBeforeView():懒加载,在view初始化之前调用
onLazyAfterView():懒加载,在view初始化之后调用
onVisible():当前Fragment对用户可见的时候调用
onInvisible():当前Fragment不可见的时候调用
Fragment的切换,在Activity使用ImmersionBar
  • 第一种,当结合viewpager使用的时候,请使用viewpager的addOnPageChangeListener的方法监听沉浸式,参考demo中FragmentThreeActivity这个类
  • 第二种,当使用show()和hide()来控制Fragment显示隐藏的时候,请在tab切换的时候使用ImmersionBar,参考demo中FragmentFourActivity这个类
使用Fragment第三方框架Fragmentation实现沉浸式
结合fragment使用.gif
  • 在Dialog中实现沉浸式,具体实现参考demo

在DialogFragment使用
   ImmersionBar.with(this, dialog).init();      
其他dialog,关闭dialog的时候必须调用销毁方法
       ImmersionBar.with(this, dialog).init();

销毁方法:

java中

       ImmersionBar.destroy(this, mAlertDialog);

kotlin中

      destroyImmersionBar(mAlertDialog)
结合dialog使用.gif
  • 在PopupWindow中实现沉浸式,具体实现参考demo

    重点是调用以下方法,但是此方法会导致有导航栏的手机底部布局会被导航栏覆盖,还有底部输入框无法根据软键盘弹出而弹出,具体适配请参考demo。

        popupWindow.setClippingEnabled(false);
    
  • 图片状态栏+彩色导航栏
     ImmersionBar.with(this)
             .transparentStatusBar()  //不写也可以,默认就是透明色
             .navigationBarColor(R.color.colorPrimary)
             .init();
    
图片状态栏+彩色导航栏.jpg
  • 全屏图片
      ImmersionBar.with(this).transparentBar().init();
    
全屏图片.jpg
  • 彩色状态栏+彩色导航栏
       ImmersionBar.with(this)
                .statusBarColor(R.color.colorPrimary)
                .navigationBarColor(R.color.btn8)
                .init();
彩色状态栏+彩色导航栏.jpg
  • 结合DrawerLayout使用
结合DrawerLayout使用.gif
  • 结合侧滑返回使用
侧滑返回.gif
  • 修改状态栏字体颜色为深色
       ImmersionBar.with(this).statusBarDarkFont(true).init();
修改状态栏字体颜色为深色.jpg
  • 设置状态栏和导航栏透明度
       ImmersionBar.with(this)
                .navigationBarColor(R.color.colorPrimary)
                .barAlpha(0.2f)
                .init();
设置状态栏和导航栏透明度.jpg
  • 隐藏状态栏
 ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_STATUS_BAR).init();
  • 隐藏导航栏
  ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_NAVIGATION_BAR).init();
  • 隐藏状态栏+导航栏
  ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_BAR).init();
  • 恢复状态栏+导航栏
  ImmersionBar.with(this).hideBar(BarHide.FLAG_SHOW_BAR).init();
  • 解决EditText和软键盘的问题

实现原理:监听界面容器的layout变化,当发生变化时,通过检查窗口可见区域高度,判断键盘是否弹起,如果弹起,则修改容器bottom padding,也就是手动实现adjustResize效果,给键盘留出显示空间。

   ImmersionBar.with(this)
               .keyboardEnable(true)  //解决软键盘与底部输入框冲突问题
               .init();
       或者
       // KeyboardPatch.patch(this).enable();
       或者,layout指的是当前布局的根节点
       // KeyboardPatch.patch(this, layout).enable();
解决EditText和软键盘的问题.gif
  • 当白色背景状态栏遇到不能改变状态栏字体为深色的设备时,解决方案
        ImmersionBar.with(this)
                  .statusBarDarkFont(true, 0.2f)
                  .init();
白色背景状态栏.png
  • 特性总结

ImmersionBar除了这些特性之外,还有其他特性哦,这里就不一一指出了,大家参考高级用法的注释,可以去实现看看哦,下面就来分析源码吧

3、源码分析

   本库采用类似建造者模式来完成,只为了方便大家更灵活的去设置状态栏和导航栏风格。实现沉浸式是分为两块,一块是android5.0以上,一块是android4.4,这两块实现原理完全不一样,在讲解原理之前先看几个概念,下面需要用到
  • View.SYSTEM_UI_FLAG_VISIBLE:显示状态栏,Activity不全屏显示(恢复到有状态的正常情况)。

  • View.INVISIBLE:隐藏状态栏,同时Activity会伸展全屏显示。

  • View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏显示,且状态栏被隐藏覆盖掉。

  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住。

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

  • View.SYSTEM_UI_LAYOUT_FLAGS:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

  • View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。

  • View.SYSTEM_UI_FLAG_LOW_PROFILE:状态栏显示处于低能显示状态(low profile模式),状态栏上一些图标显示会被隐藏。

  • android 5.0以上核心代码
     Android自5.0起,为我们提供了设置状态栏和导航栏颜色的API,我们可以自己设置状态栏和导航栏的颜色。本框架在android5.0以上就是采用官方api完成的,网上关于5.0以上的实现基本都是这样,在这里就不多说了,在这里只说一点,就是设置颜色的时候不是直接填入开发者传入的颜色值,而是采用v4包下的ColorUtils.blendARGB()方法来设置,为什么这样设计呢?有些app的状态栏并不是和标题栏颜色相同,稍微有些色差,所以在这里开发者只需要通过blendARGB()设置透明度就可以形成这种色差,而且还可以指定两种颜色之间的色差值,方便大家,android4.4上亦是如此。请看以下代码:
    
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                int uiFlags =View.SYSTEM_UI_FLAG_LAYOUT_STABLE   //防止系统栏隐藏时内容区域大小发生变化 
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;  //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态栏遮住。
                if (mBarParams.fullScreen) {
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; //Activity全屏显示,但导航栏不会被隐藏覆盖,导航栏依然可见,Activity底部布局部分会被导航栏遮住。
                }
                mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);  //取消设置透明状态栏和导航栏
                mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);  //需要设置这个才能设置状态栏颜色
                mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                        mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));  //设置状态栏颜色
                mWindow.setNavigationBarColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                        mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));  //设置导航栏颜色
                mWindow.getDecorView().setSystemUiVisibility(uiFlags); 把刚才设置的标记通过setSystemUiVisibility方法设置进去
            } 

  • android 4.4核心代码
       在4.4里就没有5.0以上这些api了,只能设置透明状态栏和导航栏,而且设置透明导航栏之后,底部布局会被导航栏遮住,那怎么办呢?好吧,只能自己写代码去实现啦。再说之前,说说我的一个思路吧。现在是2.x.x版本,在1.x.x版本的时候,4.4中实现沉浸式是引用大家非常熟悉的一个库SystemBarTint(不推荐使用了,很久没人维护了)来实现的,但是后来发现一个严重的问题,对于有导航栏的手机,设置导航栏颜色的时候,底部布局会被导航栏遮住,除此之外还有一个小问题就是当用户设置状态栏为透明色的时候,不能时刻改变bar的颜色值,are you kidding?既然出现这样的问题,就想着怎么去解决吧!就这样,我乖乖去看看SystemBarTint的源代码,哦!原理如此,发现SystemBarTint库的实现就是在状态栏和导航栏的位置自定义了可以改变背景颜色的view,然后通过window.getDecorView()得到根布局,把刚才创建的view添加进去,既然这样,为何不自己也写一个,顺便把刚才说到导航栏的问题也解决一下呢。解决方法如下代码,在这里通过注释的方法向大家说明。这里代码只是片段,不可以直接拷贝到自己的项目中
    
       if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
            mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏
                mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);//透明导航栏,设置这个,如果有导航栏,底部布局会被导航栏遮住
                setupStatusBarView(); //在根节点创建一个可以自定义颜色的状态栏创建一个假的状态栏
                if (mConfig.hasNavigtionBar())  //判断是否存在导航栏
                    setupNavBarView();   //在根节点创建一个可以自定义颜色的导航栏
                // 解决android4.4有导航栏的情况下,activity底部被导航栏遮挡的问题
                if (mConfig.hasNavigtionBar() && !mBarParams.fullScreenTemp && !mBarParams.fullScreen) {
                    if (mConfig.isNavigationAtBottom()) //判断导航栏是否在底部
                        mContentView.setPadding(0, 0, 0, mConfig.getNavigationBarHeight()); //有导航栏,获得当前布局的根节点,然后设置距离底部的padding值为导航栏的高度值
                    else
                        mContentView.setPadding(0, 0, mConfig.getNavigationBarWidth(), 0); //不在底部,设置距离右边的padding值为导航栏的宽度值
                } else {
                    mContentView.setPadding(0, 0, 0, 0); //没有导航栏,什么都不做
                }
        }
/**
     * 在根节点创建一个可以自定义颜色的状态栏
     */
    private void setupStatusBarView() {
        if (mBarParams.statusBarView == null) {
            mBarParams.statusBarView = new View(mActivity);//创建一个view
        }
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getStatusBarHeight(mActivity));
        params.gravity = Gravity.TOP; //把view设置在顶部
        if (!isNavigationAtBottom(mActivity)) {
            params.rightMargin = getNavigationBarWidth(mActivity); //横屏的时候,距离右边的距离
        }
        mBarParams.statusBarView.setLayoutParams(params);
        mBarParams.statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));//设置view的颜色
        mBarParams.statusBarView.setVisibility(View.VISIBLE);
        ViewGroup viewGroup = (ViewGroup) mBarParams.statusBarView.getParent();
        if (viewGroup != null)
            viewGroup.removeView(mBarParams.statusBarView);
        mViewGroup.addView(mBarParams.statusBarView);
    }
/**
     * 在根节点创建一个可以自定义颜色的导航栏
     */
    private void setupNavBarView() {
        if (mBarParams.navigationBarView == null) {
            mBarParams.navigationBarView = new View(mActivity);  //创建一个view
        }
        FrameLayout.LayoutParams params;
        if (isNavigationAtBottom(mActivity)) { //判断导航栏是否在底部
            params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getNavigationBarHeight(mActivity));
            params.gravity = Gravity.BOTTOM; //如果在底部把view设置在导航栏的位置
        } else {
            params = new FrameLayout.LayoutParams(getNavigationBarWidth(mActivity), FrameLayout.LayoutParams.MATCH_PARENT);
            params.gravity = Gravity.END;  //不在底部,把view设置到布局的结束位置
        }
        mBarParams.navigationBarView.setLayoutParams(params);
        if (!mBarParams.fullScreen && (mBarParams.navigationBarColorTransform == Color.TRANSPARENT)) {
            mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                    Color.BLACK, mBarParams.navigationBarAlpha));
        } else {
            mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                    mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));
        }
        mBarParams.navigationBarView.setVisibility(View.VISIBLE);
        ViewGroup viewGroup = (ViewGroup) mBarParams.navigationBarView.getParent();
        if (viewGroup != null)
            viewGroup.removeView(mBarParams.navigationBarView);
        mViewGroup.addView(mBarParams.navigationBarView);
    }
  • 状态栏字体颜色
     沉浸式原理说完了,在看看状态栏字体颜色怎么去修改吧,在android 6.0以上系统为我们提供了相关的api来设置状态栏字体颜色,如下
    
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
  }
   但是对于一些第三方rom包来说,系统api就没办法实现了,还好小米和魅族公开了各自的实现方法,如下:
  • flymeOS:
public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
   boolean result = false;
   if (window != null) {
       try {
           WindowManager.LayoutParams lp = window.getAttributes();
           Field darkFlag = WindowManager.LayoutParams.class
                   .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
           Field meizuFlags = WindowManager.LayoutParams.class
                   .getDeclaredField("meizuFlags");
           darkFlag.setAccessible(true);
           meizuFlags.setAccessible(true);
           int bit = darkFlag.getInt(null);
           int value = meizuFlags.getInt(lp);
           if (dark) {
               value |= bit;
           } else {
               value &= ~bit;
           }
           meizuFlags.setInt(lp, value);
           window.setAttributes(lp);
           result = true;
       } catch (Exception e) {

       }
   }
   return result;
}
  • MIUI:
public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
   boolean result = false;
   if (window != null) {
       Class clazz = window.getClass();
       try {
           int darkModeFlag = 0;
           Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
           Field  field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
           darkModeFlag = field.getInt(layoutParams);
           Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
           if(dark){
               extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
           }else{
               extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
           }
           result=true;
       }catch (Exception e){

       }
   }
   return result;
}
  • 状态栏和导航栏的隐藏

     android 4.1以上支持状态栏和导航栏隐藏
    
private int hideBar(int uiFlags) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            switch (mBarParams.barHide) {
                case FLAG_HIDE_BAR: //隐藏状态栏和导航栏
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.INVISIBLE;
                    break;
                case FLAG_HIDE_STATUS_BAR: //隐藏状态栏
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.INVISIBLE;
                    break;
                case FLAG_HIDE_NAVIGATION_BAR://隐藏导航栏
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
                    break;
                case FLAG_SHOW_BAR://恢复显示
                    uiFlags |= View.SYSTEM_UI_FLAG_VISIBLE;
                    break;
            }
        }
        return uiFlags | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
    }

4、总结

   至此,ImmersionBar库的用法与原理都讲完了。网上关于沉浸式的介绍铺天盖地,但是很少有人把它们封装起来,当开发者调用的时候还得自己去写大量代码,消耗大家时间。写这个库的目的就是方便大家的开发,解决大家在沉浸式方面出现的问题。如果还有不懂得地方可以去demo里看看,或者直接底下留言!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容