ImmersionBar
直接看效果图,建议下载 demo 体验,最下面有各个版本的效果图
使用(gyf 替换为 geyifeng)
3.1.1 以上版本(mavenCentral)
// 基础依赖包,必须要依赖 implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2' // kotlin 扩展(可选) implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.2' // fragment 快速实现(可选)已废弃 implementation 'com.geyifeng.immersionbar:immersionbar-components:3.2.2'
3.0.0 版本(jcenter)
// 基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' // kotlin 扩展(可选) implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0' // fragment 快速实现(可选) implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0'
版本说明
点我查看版本说明
下载 demo
点我下载 immersionBar-3.2.2.apk
关于全面屏与刘海
关于全面屏
在 manifest 加入如下配置,四选其一,或者都写
① 升级 targetSdkVersion 为 25 以上版本,现在基本都是 25 以上了,所以以下三个没有必要配置了
② 在 manifest 的 Application 节点中加入
android:resizeableActivity="true"
③ 在 manifest 的 Application 节点中加入
android:maxAspectRatio="2.4"
④ 在 manifest 的 Application 节点下加入
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
关于刘海屏
在 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" />
Api 详解
基础用法
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(); //必须调用方可应用以上所配置的参数
在 Activity 中实现沉浸式
java 用法
ImmersionBar.with(this).init();
kotlin 用法
immersionBar { statusBarColor(R.color.colorPrimary) navigationBarColor(R.color.colorPrimary) }
在 Fragment 中实现沉浸式
在 Fragment 使用 ImmersionBar
- 第一种,fragment 如果配合 viewpager2 使用的话,并且使用了 Behavior 指定了 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,直接在 fragment 的 onResume 里直接实现沉浸式
- 第二种,当使用 show()和 hide()来控制 Fragment 显示隐藏的时候,直接在 fragment 的 onResume 与 onHiddenChanged(参数 hidden 为 false)方法里实现沉浸式
第三种(废弃),你的 Fragment 直接继承SimpleImmersionFragment或者ImmersionFragment类,在 initImmersionBar 方法中实现沉浸式代码,只有当 immersionBarEnabled 返回为 true 才可以走 initImmersionBar 方法哦,不过 immersionBarEnabled 默认返回已经为 true 了,如果当前 Fragment 不想走沉浸式方法,请将 immersionBarEnabled 设置为 false第四种(废弃),如果你的 Fragment 不能继承SimpleImmersionFragment或者ImmersionFragment类,请参考SimpleImmersionFragment实现SimpleImmersionOwner接口,或者参考ImmersionFragment实现ImmersionOwner接口
在 Activity 使用 ImmersionBar
- 第一种,当结合 viewpager2 使用的时候,请使用 viewpager2 的 registerOnPageChangeCallback 的方法监听沉浸式
- 第二种,当结合 viewpager 使用的时候,请使用 viewpager 的 addOnPageChangeListener 的方法监听沉浸式,参考 demo 中FragmentThreeActivity这个类
- 第三种,当使用 show()和 hide()来控制 Fragment 显示隐藏的时候,请在 tab 切换的时候使用 ImmersionBar,参考 demo 中FragmentFourActivity这个类
使用 Fragment 第三方框架Fragmentation实现沉浸式
- 参考 demo 中FragmentFiveActivity和BaseFiveFragment这个类
在 Dialog 中实现沉浸式,具体实现参考 demo
- ①结合 dialogFragment 使用,可以参考 demo 中的BaseDialogFragment这个类
ImmersionBar.with(this).init();
②其他 dialog,关闭 dialog 的时候必须调用销毁方法
ImmersionBar.with(this, dialog).init();
销毁方法:
java 中
ImmersionBar.destroy(this, dialog);
kotlin 中
destroyImmersionBar(dialog)
在 PopupWindow 中实现沉浸式,具体实现参考 demo
重点是调用以下方法,但是此方法会导致有导航栏的手机底部布局会被导航栏覆盖,还有底部输入框无法根据软键盘弹出而弹出,具体适配请参考 demo。
popupWindow.setClippingEnabled(false);
状态栏与布局顶部重叠解决方案,六种方案根据不同需求任选其一
① 使用 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>
② 使用系统的 fitsSystemWindows 属性,使用该属性不会导致输入框与软键盘冲突问题,不要再 Fragment 使用该属性,只适合纯色状态栏
<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();
- 注意:ImmersionBar 一定要在设置完布局以后使用,
③ 使用 ImmersionBar 的 fitsSystemWindows(boolean fits)方法,只适合纯色状态栏
ImmersionBar.with(this) .fitsSystemWindows(true) //使用该属性,必须指定状态栏颜色 .statusBarColor(R.color.colorPrimary) .init();
④ 使用 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.with(this) .statusBarView(view) .init(); //或者 //ImmersionBar.setStatusBarView(this,view);
- ⑤ 使用 ImmersionBar 的 titleBar(View view)方法,原理是设置 paddingTop,可以用来适配渐变色状态栏、侧滑返回
ImmersionBar.with(this) .titleBar(view) //可以为任意 view,如果是自定义 xml 实现标题栏的话,标题栏根节点不能为 RelativeLayout 或者 ConstraintLayout,以及其子类 .init(); //或者 //ImmersionBar.setTitleBar(this, view);
- ⑥ 使用 ImmersionBar 的 titleBarMarginTop(View view)方法,原理是设置 marginTop,只适合纯色状态栏
ImmersionBar.with(this) .titleBarMarginTop(view) //可以为任意 view .statusBarColor(R.color.colorPrimary) //指定状态栏颜色,根据情况是否设置 .init(); //或者使用静态方法设置 //ImmersionBar.setTitleBarMarginTop(this,view);
解决 EditText 和软键盘的问题
- 第一种方案
ImmersionBar.with(this) .keyboardEnable(true) //解决软键盘与底部输入框冲突问题 // .keyboardEnable(true, WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE // | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) //软键盘自动弹出 .init();
- 第二种方案 不使用 keyboardEnable 方法,只需要在布局的根节点(最外层节点)加上 android:fitsSystemWindows="true"属性即可,只适合纯色状态栏
当白色背景状态栏遇到不能改变状态栏字体为深色的设备时,解决方案
ImmersionBar.with(this)
.statusBarDarkFont(true, 0.2f) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.init();
状态栏和导航栏其它方法
public static boolean hasNavigationBar(Activity activity)
判断是否存在导航栏
public static int getNavigationBarHeight(Activity activity)
获得导航栏的高度
public static int getNavigationBarWidth(Activity activity)
获得导航栏的宽度
public static boolean isNavigationAtBottom(Activity activity)
判断导航栏是否在底部
public static int getStatusBarHeight(Activity activity)
获得状态栏的高度
public static int getActionBarHeight(Activity activity)
获得 ActionBar 的高度
public static boolean hasNotchScreen(Activity activity)
是否是刘海屏
public static boolean getNotchHeight(Activity activity)
获得刘海屏高度
public static boolean isSupportStatusBarDarkFont()
判断当前设备支不支持状态栏字体设置为黑色
public static boolean isSupportNavigationIconDark()
判断当前设备支不支持导航栏图标设置为黑色
public static void hideStatusBar(Window window)
隐藏状态栏
混淆规则(proguard-rules.pro)
3.1.1 以上版本无需混淆
3.0.0 以下版本混淆规制
-keep class com.gyf.immersionbar.* {*;}
-dontwarn com.gyf.immersionbar.**
问题汇总
点我问题汇总
效果图
说明
- 这是状态栏
- 这是导航栏(有些手机没有导航栏)
动态图
android 6.0 有导航栏效果
android 4.4 有导航栏效果
android 4.4 没有导航栏效果
特别鸣谢
- 感谢zhangzhen92、 yutouxiansheng 、MrWhhh提供测试
联系我
- QQ 群 314360549(问题交流)