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

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

先看两个概念

  • 状态栏

    image
  • 导航栏

    image

1、引入

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

image
dependencies {
    compile 'com.gyf.barlibrary:barlibrary:2.3.0'
}

2、特性

1)基本介绍

基础用法,建议在BaseActivity里调用

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ImmersionBar.with(this).init(); //初始化,默认透明状态栏和黑色导航栏
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ImmersionBar.with(this).destroy(); //不调用该方法,如果界面bar发生改变,在不关闭app的情况下,退出此界面再进入将记忆最后一次bar改变的状态
    }
}
  • 高级用法,如果基础用法不能满足你的需求,可以试试这里的方法
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)   //状态栏字体是深色,不写默认为亮色
                 .flymeOSStatusBarFontColor(R.color.btn3)  //修改flyme OS状态栏字体颜色
                 .fullScreen(true)      //有导航栏的情况下,activity全屏显示,也就是activity最下面被导航栏覆盖,不写默认非全屏
                 .hideBar(BarHide.FLAG_HIDE_BAR)  //隐藏状态栏或导航栏或两者,不写默认不隐藏
                 .addViewSupportTransformColor(toolbar)  //设置支持view变色,可以添加多个view,不指定颜色,默认和状态栏同色,还有两个重载方法
                 .titleBar(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支持
                 .addTag("tag")  //给以上设置的参数打标记
                 .getTag("tag")  //根据tag获得沉浸式参数
                 .reset()  //重置所以沉浸式参数
                 .keyboardEnable(true)  //解决软键盘与底部输入框冲突问题,默认为false
                 .setOnKeyboardListener(new OnKeyboardListener() {    //软键盘监听回调
                   @Override
                   public void onKeyboardChange(boolean isPopup, int keyboardHeight) {
                       LogUtils.e(isPopup);  //isPopup为true,软键盘弹出,为false,软键盘关闭
                   }
              })
                 .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)  //单独指定软键盘模式
                 .init();  //必须调用方可沉浸式

2)详细介绍

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

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

https://upload-images.jianshu.io/upload_images/4776932-7f0f212167b8c81c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700

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

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值为状态栏的高度值

    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️⃣种,最后来一张效果图

image.png
  • 在Fragment中实现沉浸式

注意:2.2.6版本已将ImmersionFragment这个类标记为过时,请用户自行使用懒加载方式实现

  • 在Fragment使用ImmersionBar

    第一种,当结合viewpager使用的时候,请使用懒加载的形式,参考demo中的BaseLazyFragment这个类
    第二种,当使用show()和hide()来控制Fragment显示隐藏的时候,参考demo中的BaseTwoFragment这个类

    注意:

    • 2.2.7版本以后别忘了在Fragment的onDestroy方法里销毁沉浸式了,2.2.7版本之前不需要调用
@Override
   protected void onDestroy() {
       super.onDestroy();
       if (mImmersionBar != null)
          mImmersionBar.destroy();  
   }

以show()和hide()方式控制Fragment显示隐藏,别忘了重写onHiddenChanged方法,如下

@Override
     public void onHiddenChanged(boolean hidden) {
         super.onHiddenChanged(hidden);
         if (!hidden && mImmersionBar != null)
            mImmersionBar.init();
     }

  • 在Activity使用ImmersionBar

    第一种,当结合viewpager使用的时候,请使用viewpager的addOnPageChangeListener的方法监听沉浸式,参考demo中FragmentThreeActivity这个类
    第二种,当使用show()和hide()来控制Fragment显示隐藏的时候,请在tab切换的时候使用ImmersionBar,参考demo中FragmentFourActivity这个类
    参考demo中FragmentFiveActivityBaseFiveFragment这个类
image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339

推荐阅读更多精彩内容