我正在参加创作者训练营第6期,点击了解活动详情

前言

在咱们开发运用的过程中,关于状况栏的办理是不得不提的工作,一般咱们经过开源的一些第三方库来办理,并没有了解它完成原理。

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

状况栏说的便是咱们顶部的那个大黑边了,一个运用的状况栏,咱们一般常用的几种操作如下:

  1. 设置状况栏的布景色彩(假如是6.0以下需求兼容处理白色布景)
  2. 设置状况栏的布景图片
  3. 设置状况栏敞开沉溺式和封闭沉溺式
  4. 设置状况栏文本图标色彩(黑色与白色)
  5. 设置指定布局适配状况栏高度

一般来说操作状况栏有两种思路,一种是直接操作体系状况栏,一般运用一个东西类来完成。另一种是弃用体系状况,运用宿主自界说View的计划替代 DecorView 中的真正布局,距离的操作’状况栏’。这里的状况栏打引号,因为这个状况栏是咱们自界说View完成的。

下面咱们来看看他们别离怎样完成与操作。

一、体系原生状况栏

因为Android的状况栏处理不同的体系版别处理的办法不同,这里只兼容到4.4版别以上,也是咱们常用的最低版别。

1.1 状况栏办理东西类

一般咱们经过状况栏的东西类增加一些Flag,操作办理体系的状况栏。

/**
 * 状况栏通明,状况栏黑色文字,状况栏色彩,沉溺式状况栏
 */
public class StatusBarUtils {
    public static int DEFAULT_COLOR = 0;
    public static float DEFAULT_ALPHA = 0;
    /**
     * 设置状况栏布景色彩
     */
    public static void setColor(Activity activity, @ColorInt int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(color);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup systemContent = activity.findViewById(android.R.id.content);
            View statusBarView = new View(activity);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
            statusBarView.setBackgroundColor(color);
            systemContent.getChildAt(0).setFitsSystemWindows(true);
            systemContent.addView(statusBarView, 0, lp);
        }
    }
    public static void immersive(Activity activity) {
        immersive(activity, DEFAULT_COLOR, DEFAULT_ALPHA);
    }
    public static void immersive(Activity activity, int color, @FloatRange(from = 0.0, to = 1.0) float alpha) {
        immersive(activity.getWindow(), color, alpha);
    }
    public static void immersive(Activity activity, int color) {
        immersive(activity.getWindow(), color, 1f);
    }
    public static void immersive(Window window) {
        immersive(window, DEFAULT_COLOR, DEFAULT_ALPHA);
    }
    public static void immersive(Window window, int color) {
        immersive(window, color, 1f);
    }
    public static void immersive(Window window, int color, @FloatRange(from = 0.0, to = 1.0) float alpha) {
        if (Build.VERSION.SDK_INT >= 21) {
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(mixtureColor(color, alpha));
            int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
            systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            window.getDecorView().setSystemUiVisibility(systemUiVisibility);
        } else if (Build.VERSION.SDK_INT >= 19) {
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            setTranslucentView((ViewGroup) window.getDecorView(), color, alpha);
        } else if (Build.VERSION.SDK_INT > 16) {
            int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
            systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            window.getDecorView().setSystemUiVisibility(systemUiVisibility);
        }
    }
    /**
     * 创建假的通明栏
     */
    public static void setTranslucentView(ViewGroup container, int color, @FloatRange(from = 0.0, to = 1.0) float alpha) {
        if (Build.VERSION.SDK_INT >= 19) {
            int mixtureColor = mixtureColor(color, alpha);
            View translucentView = container.findViewById(android.R.id.custom);
            if (translucentView == null && mixtureColor != 0) {
                translucentView = new View(container.getContext());
                translucentView.setId(android.R.id.custom);
                ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(container.getContext()));
                container.addView(translucentView, lp);
            }
            if (translucentView != null) {
                translucentView.setBackgroundColor(mixtureColor);
            }
        }
    }
    public static int mixtureColor(int color, @FloatRange(from = 0.0, to = 1.0) float alpha) {
        int a = (color & 0xff000000) == 0 ? 0xff : color >>> 24;
        return (color & 0x00ffffff) | (((int) (a * alpha)) << 24);
    }
    // ========================  状况栏字体色彩设置  ↓ ================================
    /**
     * 设置状况栏黑色字体图标
     */
    public static boolean setStatusBarBlackText(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Window window = activity.getWindow();
            View decorView = window.getDecorView();
            decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            return true;
        }
        return false;
    }
    /**
     * 设置状况栏白色字体图标
     */
    public static boolean setStatusBarWhiteText(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Window window = activity.getWindow();
            View decorView = window.getDecorView();
            decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            return true;
        }
        return false;
    }
    // ========================  状况栏字体色彩设置  ↑================================
    // 在某些机子上存在不同的density值,所以增加两个虚拟值
    private static int sStatusBarHeight = -1;
    private static float sVirtualDensity = -1;
    private final static int STATUS_BAR_DEFAULT_HEIGHT_DP = 25; // 大部分状况栏都是25dp
    /**
     * 获取状况栏的高度。
     */
    public static int getStatusBarHeight(Context context) {
        if (sStatusBarHeight == -1) {
            initStatusBarHeight(context);
        }
        return sStatusBarHeight;
    }
    private static void initStatusBarHeight(Context context) {
        Class<?> clazz;
        Object obj = null;
        Field field = null;
        try {
            clazz = Class.forName("com.android.internal.R$dimen");
            obj = clazz.newInstance();
            if (DeviceUtils.isMeizu()) {
                try {
                    field = clazz.getField("status_bar_height_large");
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
            if (field == null) {
                field = clazz.getField("status_bar_height");
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
        if (field != null && obj != null) {
            try {
                int id = Integer.parseInt(field.get(obj).toString());
                sStatusBarHeight = context.getResources().getDimensionPixelSize(id);
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
        if (DeviceUtils.isTablet(context)
                && sStatusBarHeight > CommUtils.dip2px(STATUS_BAR_DEFAULT_HEIGHT_DP)) {
            //状况栏高度大于25dp的平板,状况栏通常在下方
            sStatusBarHeight = 0;
        } else {
            if (sStatusBarHeight <= 0) {
                if (sVirtualDensity == -1) {
                    sStatusBarHeight = CommUtils.dip2px(STATUS_BAR_DEFAULT_HEIGHT_DP);
                } else {
                    sStatusBarHeight = (int) (STATUS_BAR_DEFAULT_HEIGHT_DP * sVirtualDensity + 0.5f);
                }
            }
        }
    }
    // ========================  适配状况栏高度  ↓ ================================
    /**
     * 适配状况栏高度的View - 设置Padding
     */
    public static void fitsStatusBarViewPadding(View view) {
        //增加高度
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        lp.height += getStatusBarHeight(view.getContext());
        //设置PaddingTop
        view.setPadding(view.getPaddingLeft(),
                view.getPaddingTop() + getStatusBarHeight(view.getContext()),
                view.getPaddingRight(),
                view.getPaddingBottom());
    }
    /**
     * 适配状况栏高度的View - 设置Margin
     */
    public static void fitsStatusBarViewMargin(View view) {
        if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            //现已增加过了不要再次设置
            if (view.getTag() != null && view.getTag().equals("fitStatusBar")) {
                return;
            }
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
            int marginTop = layoutParams.topMargin;
            int setMarginTop = marginTop + getStatusBarHeight(view.getContext());
            view.setTag("fitStatusBar");
            layoutParams.topMargin = setMarginTop;
            view.requestLayout();
        }
    }
    /**
     * 适配状况栏高度的View - 运用布局包裹
     */
    public static void fitsStatusBarViewLayout(View view) {
        ViewParent fitParent = view.getParent();
        if (fitParent != null) {
            if (((fitParent instanceof LinearLayout) &&
                    ((ViewGroup) fitParent).getTag() != null &&
                    ((ViewGroup) fitParent).getTag().equals("fitLayout"))) {
                //现已增加过了不要再次设置
                return;
            }
            //给当时布局包装一个习惯布局
            ViewGroup fitGroup = (ViewGroup) fitParent;
            fitGroup.removeView(view);
            LinearLayout fitLayout = new LinearLayout(view.getContext());
            fitLayout.setOrientation(LinearLayout.VERTICAL);
            fitLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            fitLayout.setTag("fitLayout");
            //先加一个状况栏高度的布局
            View statusView = new View(view.getContext());
            statusView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(view.getContext())));
            fitLayout.addView(statusView);
            ViewGroup.LayoutParams fitViewParams = view.getLayoutParams();
            fitLayout.addView(view);
            fitGroup.addView(fitLayout);
        }
    }
}
1.2 体系状况栏的布景和文本色彩处理

经过东西类操作的方法,咱们一般封装到BaseActivity中,比如界说一些办法:

    /**
     * 设置顶部状况栏的色彩(默许为白色布景-黑色文字)
     */
    protected fun setStatusBarColor(): Int {
        //假如状况栏文字能变黑那么布景设置为白色,否则回来布景灰色文本默许为白色
        return if (StatusBarUtils.setStatusBarBlackText(this)) {
            Color.WHITE
        } else {
            Color.parseColor("#B0B0B0")
        }
    }
    /**
     * 动态的设置状况栏色彩
     * 当色彩为白色的时分显示白底黑字
     * 其他色彩为其他色彩底白色字
     * 一般由子类重写
     */
    fun setStatusBarColor(color: Int) {
        if (color == Color.WHITE) {
            //变黑色文字成功
            if (StatusBarUtils.setStatusBarBlackText(this)) {
                StatusBarUtils.setColor(this, Color.WHITE)
            } else {
                StatusBarUtils.setColor(this, Color.parseColor("#B0B0B0"))
            }
        } else {
            //变为白色文字成功
            StatusBarUtils.setStatusBarWhiteText(this)
            StatusBarUtils.setColor(this, color)
        }
    }
    fun setStatusBarBlackText(){
        StatusBarUtils.setStatusBarBlackText(this)
    }
    fun setStatusBarWhiteText(){
        StatusBarUtils.setStatusBarWhiteText(this)
    }

咱们能够再基类中运用默许的状况栏布景色彩、文本色彩。然后子类想重写的话直接调用办法设置即可,一般来说就能满意咱们的需求。

关于状况栏文本色彩6.0以下是无法修改为黑色的文本的(没有运用魅族小米的兼容计划,没必要,假如咱们想要魅族小米4.4 – 6.0的黑色文本兼容,能够网上找找,也能够留言),需求做一下兼容,当低版别设置状况栏布景色彩为白色的时分,咱们修改为灰色展现即可。

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

经过基类的封装,咱们确实能够很便利的完成状况栏中布景色彩与文本色彩的处理,那么沉溺式的处理怎样处理呢?

1.3 体系状况栏的沉溺式处理

一般沉溺式的处理,咱们在oncreate办法中调用东西类办法。

    StatusBarUtils.setStatusBarWhiteText(this)
    StatusBarUtils.immersive(this)

确实是完成了沉溺式,一般情况下也就够用了,可是假如咱们需求改变,或许结构改变,就会有问题,这样的沉溺式假如设置了就不能撤销,假如咱们的场景是顶部的Title和状况栏是一张图片布景,然后下面的列表翻滚到图片消失之后状况栏不沉溺式了,状况栏布景色彩变为白色,这…

或许咱们运用的是单Activity+多Fragment的结构,咱们一个Activity中的根Fragment设置为沉溺式,那么在其他的子Fragment中咱们又不需求沉溺式。这…

一般在这样的计划中咱们能够经过自界说的状况栏View,和自界说的TitleBar的处理。

能够运用规范TitleBar的页面,咱们能够经过TitleBar设置对应的状况栏,例如:

     <com.guadou.lib_baselib.view.titlebar.EasyTitleBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:Easy_hasStatusPadding="true"
        app:Easy_title="吐司-弹窗-banner"
        app:Easy_titleBarBackground="#ff0000" />

例如 hasStatusPadding 特点。便是能够自在的设置TitleBar顶部的状况栏距离。就能够自在的操控状况栏的高度与色彩或布景的改变。

可是假如咱们顶部是自界说的布局,比如搜索框 + lottie动画之类的全体布局,那咱们怎样办?

此处就需求运用咱们自界说的状况栏布局:

public class StatusbarGrayView extends View {
    public StatusbarGrayView(Context context) {
        super(context);
    }
    public StatusbarGrayView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public StatusbarGrayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec); //得到宽度设置方法
        int widthSize = MeasureSpec.getSize(widthMeasureSpec); //得到宽度设置方法
        int heightMode = MeasureSpec.getMode(heightMeasureSpec); //得到高度设置方法
        //假如设置高度为wrap-content自习惯 那么固定设置为状况栏高度
        if (heightMode == MeasureSpec.AT_MOST) {
            if (widthMode == MeasureSpec.EXACTLY) {
                setMeasuredDimension(widthSize, EasyUtil.getStateBarHeight(getContext()));
            } else {
                setMeasuredDimension(1, EasyUtil.getStateBarHeight(getContext()));
            }
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        ViewGroup parent = (ViewGroup) getParent();
        if (parent == null) return;
        Drawable drawable = parent.getBackground();
        if (drawable instanceof ColorDrawable) {
            int color = ((ColorDrawable) drawable).getColor();
            if (color == Color.WHITE || color == CommUtils.getColor(R.color.white)) {
                setBackgroundColor(Build.VERSION.SDK_INT < 23 ? CommUtils.getColor(R.color.status_bar_gray_bg) : Color.WHITE);
            } else {
                setBackgroundColor(Color.TRANSPARENT);
            }
        } else {
            setBackgroundColor(Color.TRANSPARENT);
        }
    }
}

咱们运用自界说View,放在自界说搜索框Title的上面即可完成状况高度的自在操控,

到此咱们就能把Activity悉数沉溺式,然后由自界说的TitleBar来办理咱们的状况,或许有自界说状况View来办理状况栏。

到此体系状况栏的办理现已能完成绝大部分的作用处理,缺点是完成的计划不统一吗,不同的作用需求不同的计划来处理,假如是他人接手你的项目可能会比较蒙。

而另一种计划也是我比较推荐的计划便是运用宿主的方法替代体系的状况栏布局。

二、自界说宿主办理状况栏

详细的计划是,咱们setContentView的时分,把体系的DecorView中的View取出,替换成咱们自界说的布局,内部包括一个自界说的状况栏,和一个FramLayout,咱们把之前的布局取出增加到咱们自界说布局中,然后默许把当时Activity沉溺式之后,当下操作的StatusBar便是咱们的自界说StatusBarView了。

这样操作状况栏便是操作咱们的View目标了,想怎样玩就怎样玩,愈加灵敏了,设置色彩,Drawable,Alpha等都是非常的便利,想设置沉溺式直接Gone掉咱们的自界说StatusBarView即可,想不用沉溺式,那么就把StatusBarView设置为VISIBLE即可。

而且对状况栏的各种操作不受到体系版别影响,就一个字,灵敏!

界说咱们自界说状况栏View目标

/**
 * 自界说状况栏的View,用于StatusBarHostLayout中运用
 */
class StatusView extends View {
    private int mBarSize;
    public StatusView(Context context) {
        this(context, null, 0);
    }
    public StatusView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public StatusView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mBarSize = StatusBarHostUtils.getStatusBarHeight(context);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mBarSize);
    }
    //获取到当时的状况栏高度
    public int getStatusBarHeight() {
        return mBarSize;
    }
}

核心的宿主替代类:

/**
 * 宿主的布局
 */
@SuppressLint("ViewConstructor")
public class StatusBarHostLayout extends LinearLayout {
    private Activity mActivity;
    private StatusView mStatusView;
    private FrameLayout mContentLayout;
    StatusBarHostLayout(Activity activity) {
        super(activity);
        this.mActivity = activity;
        //加载自界说的宿主布局
        if (mStatusView == null && mContentLayout == null) {
            setOrientation(LinearLayout.VERTICAL);
            mStatusView = new StatusView(mActivity);
            mStatusView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            addView(mStatusView);
            mContentLayout = new FrameLayout(mActivity);
            mContentLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f));
            addView(mContentLayout);
        }
        //替换宿主的contentView为外界设置的View
        replaceContentView();
        //设置原生的状况栏沉溺式,运用自界说的状况栏布局
        StatusBarHostUtils.immersiveStatusBar(mActivity);
        StatusBarHostUtils.setStatusBarColor(mActivity, Color.TRANSPARENT);
    }
    private void replaceContentView() {
        Window window = mActivity.getWindow();
        ViewGroup contentLayout = window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
        if (contentLayout.getChildCount() > 0) {
            //先找到DecorView的容器移除掉现已设置的ContentView
            View contentView = contentLayout.getChildAt(0);
            contentLayout.removeView(contentView);
            ViewGroup.LayoutParams contentParams = contentView.getLayoutParams();
            //外部设置的ContentView增加到宿主中来
            mContentLayout.addView(contentView, contentParams.width, contentParams.height);
        }
        //再把整个宿主增加到Activity对应的DecorView中去
        contentLayout.addView(this, -1, -1);
    }
    /**
     * 设置状况栏文本色彩为黑色
     */
    public StatusBarHostLayout setStatusBarBlackText() {
        StatusBarHostUtils.setStatusBarDarkFont(mActivity, true);
        return this;
    }
    /**
     * 设置状况栏文本色彩为白色
     */
    public StatusBarHostLayout setStatusBarWhiteText() {
        StatusBarHostUtils.setStatusBarDarkFont(mActivity, false);
        return this;
    }
    /**
     * 设置自界说状况栏布局的布景色彩
     */
    public StatusBarHostLayout setStatusBarBackground(int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mStatusView.setBackgroundColor(color);
        } else {
            //6.0以下不能白色状况栏
            YYLogUtils.w("当时的状况色彩1:" + color);
            if (color == Color.WHITE) {
                color = Color.parseColor("#B0B0B0");
            }
            mStatusView.setBackgroundColor(color);
        }
        return this;
    }
    /**
     * 设置自界说状况栏布局的布景图片
     */
    public StatusBarHostLayout setStatusBarBackground(Drawable drawable) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mStatusView.setBackground(drawable);
        } else {
            mStatusView.setBackgroundDrawable(drawable);
        }
        return this;
    }
    /**
     * 设置自界说状况栏布局的通明度
     */
    public StatusBarHostLayout setStatusBarBackgroundAlpha(int alpha) {
        Drawable background = mStatusView.getBackground();
        if (background != null) {
            background.mutate().setAlpha(alpha);
        }
        return this;
    }
    /**
     * 给指定的布局适配状况栏高度,设置paddingTop
     */
    public StatusBarHostLayout setViewFitsStatusBarView(View view) {
        //设置MaginTop的办法
        if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            //现已增加过了不要再次设置
            if (view.getTag() != null && view.getTag().equals("fitStatusBar")) {
                return this;
            }
            ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
            int marginTop = layoutParams.topMargin;
            int setMarginTop = marginTop + mStatusView.getStatusBarHeight();
            view.setTag("fitStatusBar");
            layoutParams.topMargin = setMarginTop;
            view.requestLayout();
        }
        return this;
    }
    /**
     * 设置自界说状况栏的沉溺式
     */
    public StatusBarHostLayout setStatusBarImmersive(boolean needImmersive) {
        layoutimmersive(needImmersive);
        return this;
    }
    //详细的沉溺式逻辑
    private void layoutimmersive(boolean needImmersive) {
        if (needImmersive) {
            mStatusView.setVisibility(GONE);
        } else {
            mStatusView.setVisibility(VISIBLE);
            mStatusView.setBackgroundColor(ContextCompat.getColor(mActivity, R.color.colorPrimary));
        }
    }
}

界说一个状况栏设置入口:

/**
 * 宿主替换布局的办法办理状况栏与内容的布局
 */
public class StatusBarHost {
    private StatusBarHost() {
    }
    public static StatusBarHostLayout inject(Activity activity) {
        Window window = activity.getWindow();
        ViewGroup contentLayout = window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
        if (contentLayout.getChildCount() > 0) {
            View contentView = contentLayout.getChildAt(0);
            //假如当时是宿主的包装类,直接强转
            if (contentView instanceof StatusBarHostLayout) {
                return (StatusBarHostLayout) contentView;
            }
        }
        //假如不是咱们封装一个宿主包装类
        return new StatusBarHostLayout(activity);
    }
}

就简略的三个类即可完成状况栏的办理,内部的东西类和上面的东西类相似,只需求沉溺式的处理与状况栏文本色彩的切换。

下面看看怎样运用:

什么都不加的默许作用

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

咱们加上状况栏色彩白色

 val hostLayout = StatusBarHost.inject(this)
            .setStatusBarBackground(color(R.color.white))
            .setStatusBarBlackText()

作用如下:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

假如是6.0版别一下,是这样的作用

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

切换状况栏色彩为红色

     findViewById<View>(R.id.btn_bg_color).click {
            hostLayout.setStatusBarBackground(Color.RED)
        }

作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

因为是咱们自己的View,咱们还能设置状况栏布景Drawable

      findViewById<View>(R.id.btn_bg_img).click {
            hostLayout.setStatusBarBackground(getDrawable(R.drawable.statusbar_image_1))
        }

作用如下:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

6.0 一下的作用也是一样的

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

沉溺式的处理,一句话就能够:

  val hostLayout = StatusBarHost.inject(this)
            .setStatusBarImmersive(true)

作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

那咱们撤销沉溺式

     findViewById<View>(R.id.btn_002).click {
            hostLayout.setStatusBarImmersive(false)
        }

作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

咱们能够自在的设置View的状况栏距离

      findViewById<View>(R.id.btn_003).click {
            hostLayout.setViewFitsStatusBarView(findViewById(R.id.title_view))
        }

作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!
还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

翻滚突变状况栏色彩:

    override fun init() {
        val startColor: Int = color(R.color.white)
        val endColor: Int = color(R.color.colorPrimary)
        //默许的状况处理
        hostLayout = StatusBarHost.inject(this)
            .setStatusBarBackground(startColor)
            .setStatusBarWhiteText()
        //监听翻滚
        val myScrollView = findViewById<NestedScrollView>(R.id.my_scroll)
        easyTitleBar = findViewById(R.id.easy_title)
        easyTitleBar.setBackgroundColor(startColor)
        val topImg = findViewById<ImageView>(R.id.iv_top_img)
        SizeUtils.forceGetViewSize(topImg) {
            imgHeight = it.height
        }
        myScrollView.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
            if (imgHeight > 0) {
                val scrollDistance = Math.min(scrollY, imgHeight)
                val fraction: Float = scrollDistance.toFloat() / imgHeight.toFloat()
                setTitleStatusBarAlpha(CalculateUtils.evaluate(fraction, startColor, endColor))
            }
        })
    }
    private fun setTitleStatusBarAlpha(color: Int) {
        easyTitleBar.setBackgroundColor(color)
        hostLayout.setStatusBarBackground(color)
    }

6.0 以上作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

6.0 以下作用:

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!

能够看到相比体系状况栏的办理,咱们运用宿主的计划一样的能够悉数完成,而且运用起来办法愈加的统一,愈加的便捷一些。

总结

两种计划都能够,看咱们习惯运用的是哪一种计划。

假如是办理体系的状况栏,那么咱们在一些特殊场景和单Activity的架构中就没有那么灵敏,需求配合自界说的TitleBar和自界说StatusBarView来处理。

假如是运用宿主计划办理状况栏,那么咱们运用起来兼容性会更好一些,可是咱们需求了解它完成的原理,才能更便利和灵敏的做出对应的操作,需求有一些学习成本。

你们用的都是哪一种计划呢?

本文悉数代码都已悉数贴出,假如咱们有兴趣也能够查看源码自取。

好了,本期内容如讲的不到位或错漏的地方,期望同学们能够指出沟通。

假如感觉本文对你有一点点点的启示,还望你能点赞支撑一下,你的支撑是我最大的动力。

Ok,这一期就此结束。

还用第三方库管理状态栏吗?Android关于状态栏管理的几种方案实现!