本文最后更新于 798 天前
自定义状态栏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);
}
}
使用
val hostLayout = StatusBarHost.inject(this)
.setStatusBarBackground(color(R.color.white))
.setStatusBarBlackText()
hostLayout.setStatusBarBackground(Color.RED)
hostLayout.setStatusBarBackground(getDrawable(R.drawable.statusbar_image_1))
hostLayout.setStatusBarImmersive(true)