Android实现沉浸式状态栏(已验证,支持Fragment,支持Android 5.0及其以上版本,支持AndroidX)

自从app换新需求(要做沉浸式状态栏),用过几种沉浸式状态栏,发现根本不能完全兼容Android 4.4以上所有版本,经过研究发现此种方法的确可行,在此记录。

以下代码在项目里,项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

1.添加依赖

//沉浸式状态栏框架导入
// 基础依赖包,必须要依赖
implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
// fragment快速实现(可选)
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0'

2.在values文件夹下的styles.xml文件下添加,并且把之前的名为AppTheme的style注释掉。

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowBackground">@android:color/white</item>
</style>

3.在清单文件的application标签下添加(如果没有则添加,如有则删除之前的,然后再添加)

android:theme="@style/AppTheme"

4.在清单文件的application标签内添加

<!-- 沉浸式状态栏适配 -->
<meta-data
    android:name="android.max_aspect"
    android:value="2.4" />

5.定义一个ImmerseGroup类

//沉浸式状态栏Toolbar辅助类,避免Toolbar设置fitSystemWindows="true"当软键盘弹出时Toolbar被拉伸
public class ImmerseGroup extends FrameLayout {

    public ImmerseGroup(Context context) {
        super(context);
    }

    public ImmerseGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ImmerseGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 0);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

6.在layout文件最上方中添加

<com.xxx.custom_view.ImmerseGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorWhiteA"
        android:minHeight="?attr/actionBarSize"
        app:contentInsetStart="0dp">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_48">

            <FrameLayout
                android:id="@+id/layout_back"
                android:layout_width="@dimen/dp_36"
                android:layout_height="match_parent"
                tools:ignore="UselessParent">

                <ImageView
                    android:id="@+id/imv_back"
                    android:layout_width="@dimen/dp_6"
                    android:layout_height="@dimen/dp_11"
                    android:layout_gravity="center"
                    android:src="@mipmap/icon_arrowhead_left"
                    tools:ignore="ContentDescription" />

            </FrameLayout>

            <TextView
                android:id="@+id/tev_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="@string/feedback"
                android:textColor="@color/colorBlackF"
                android:textSize="@dimen/sp_17" />

        </FrameLayout>

    </androidx.appcompat.widget.Toolbar>

</com.xxx.custom_view.ImmerseGroup>

在Activity中添加函数

/**
 * 设置沉浸式状态栏
 * @param isDarkFont 状态栏字体是否是深色的
 */
protected void setToolbar(boolean isDarkFont, int color) {
    if (isDarkFont) {
        ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,
//如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarColor(color)     //状态栏颜色,不写默认透明色
                .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init();
    } else {
        ImmersionBar.with(this)
                .statusBarColor(color)     //状态栏颜色,不写默认透明色
                .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init();
    }
}

//要在setContentView(R.layout.xxx)之后调用

setToolbar(true, getResources().getColor(R.color.colorWhiteB));

7.在Fragment中使用

在Fragment的layout文件最上方中添加

<View
    android:id="@+id/status_bar_view"
    android:layout_width="match_parent"
    android:layout_height="0dp" />

<androidx.appcompat.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_73"
    android:background="@color/colorWhiteB"
    android:minHeight="?attr/actionBarSize"
    android:orientation="vertical"
    app:contentInsetStart="0dp"
    tools:ignore="UselessParent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_73"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_25" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_48"
            android:visibility="visible"
            tools:ignore="UselessParent">

            <TextView
                android:id="@+id/tev_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="@string/historical_orders"
                android:textColor="@color/colorBlackF"
                android:textSize="@dimen/sp_17" />

            <FrameLayout
                android:id="@+id/layout_search"
                android:layout_width="@dimen/dp_37"
                android:layout_height="match_parent"
                android:layout_gravity="end"
                android:layout_marginEnd="@dimen/dp_37"
                android:visibility="visible"
                tools:ignore="UselessParent">

                <ImageView
                    android:id="@+id/imv_search"
                    android:layout_width="@dimen/dp_15"
                    android:layout_height="@dimen/dp_15"
                    android:layout_gravity="center"
                    android:src="@mipmap/icon_search_order_black"
                    tools:ignore="ContentDescription" />

            </FrameLayout>

            <FrameLayout
                android:id="@+id/layout_filter"
                android:layout_width="@dimen/dp_37"
                android:layout_height="match_parent"
                android:layout_gravity="end"
                android:visibility="visible"
                tools:ignore="UselessParent">

                <ImageView
                    android:id="@+id/imv_filter"
                    android:layout_width="@dimen/dp_15"
                    android:layout_height="@dimen/dp_15"
                    android:layout_gravity="center"
                    android:src="@mipmap/icon_filter"
                    tools:ignore="ContentDescription" />

            </FrameLayout>

        </FrameLayout>

    </LinearLayout>

</androidx.appcompat.widget.Toolbar>

在Fragment的中添加

protected View statusBarView;
protected Toolbar toolbar;
protected void fitsLayoutOverlap() {
    if (statusBarView != null) {
        ImmersionBar.setStatusBarView(activity, statusBarView);
    } else {
        ImmersionBar.setTitleBar(activity, toolbar);
    }
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //旋转屏幕为什么要重新设置布局与状态栏重叠呢?因为旋转屏幕有可能使状态栏高度不一样,
//如果你是使用的静态方法修复的,所以要重新调用修复
    fitsLayoutOverlap();
}

在Fragment的onCreateView函数中添加

rootView = inflater.inflate(R.layout.xxx, container, false);
statusBarView = rootView.findViewById(R.id.status_bar_view);
toolbar = rootView.findViewById(R.id.toolbar);

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值