android 工具栏透明,android状态栏透明总结

首先明确一下沉浸式状态栏的概念有两种类型顶部是ImageView这种需要将其填充到状态栏。

bVcG9eG

2.顶部是ActionBar这种不需要填充到状态栏。

bVcG9fs

而上面的第二种情况覆盖了绝大部分页面,所以下面的思路也是基于这点来实现。

第一步:

在BaseActivity里面实现如下代码public abstract class BaseActivity extends AppCompatActivity {

@Override

protected final void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setStatusBar();

}

protected void setStatusBar() {

//这里做了两件事情,1.使状态栏透明并使contentView填充到状态栏 2.预留出状态栏的位置,防止界面上的控件离顶部靠的太近。这样就可以实现开头说的第二种情况的沉浸式状态栏了

StatusBarUtil.setTransparent(this);

}

}

看下StatusBarUtil.setTransparent(this)具体的实现/**

* 设置状态栏全透明

*

* @param activity 需要设置的activity

*/

public static void setTransparent(Activity activity) {

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {

return;

}

transparentStatusBar(activity);

setRootView(activity);

}

/**

* 使状态栏透明

*/

@TargetApi(Build.VERSION_CODES.KITKAT)

private static void transparentStatusBar(Activity activity) {

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);

//需要设置这个flag contentView才能延伸到状态栏

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

//状态栏覆盖在contentView上面,设置透明使contentView的背景透出来

activity.getWindow().setStatusBarColor(Color.TRANSPARENT);

} else {

//让contentView延伸到状态栏并且设置状态栏颜色透明

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

}

}

/**

* 设置根布局参数

*/

private static void setRootView(Activity activity) {

ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);

for (int i = 0, count = parent.getChildCount(); i < count; i++) {

View childView = parent.getChildAt(i);

if (childView instanceof ViewGroup) {

childView.setFitsSystemWindows(true);

((ViewGroup) childView).setClipToPadding(true);

}

}

}

经过这样的设置基本上大部分界面都适配了沉浸式状态栏了,针对需要适配imageView填充到状态栏或者需要单独设置状态栏颜色和透明度的我们可以在BaseActivity 的子类重写setStatusBar方法来单独适配。

第二步:先说简单的,单独设置状态栏颜色和透明度这种情况//重写这个方法

protected void setStatusBar() {

StatusBarUtil.setColor(...);

}

/**

* 设置状态栏颜色

*

* @param activity 需要设置的activity

* @param color 状态栏颜色值

* @param statusBarAlpha 状态栏透明度

*/

public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {

//5.0以上版本直接设置状态栏颜色透明度

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(calculateStatusColor(color, statusBarAlpha));

//4.4-5.0版本通过伪装一个状态栏来设置颜色和透明度

} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();

View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);

if (fakeStatusBarView != null) {

if (fakeStatusBarView.getVisibility() == View.GONE) {

fakeStatusBarView.setVisibility(View.VISIBLE);

}

fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));

} else {

decorView.addView(createStatusBarView(activity, color, statusBarAlpha));

}

setRootView(activity);

}

}

/**

* 计算状态栏颜色

*

* @param color color值

* @param alpha alpha值

* @return 最终的状态栏颜色

*/

private static int calculateStatusColor(@ColorInt int color, int alpha) {

if (alpha == 0) {

return color;

}

float a = 1 - alpha / 255f;

int red = color >> 16 & 0xff;

int green = color >> 8 & 0xff;

int blue = color & 0xff;

red = (int) (red * a + 0.5);

green = (int) (green * a + 0.5);

blue = (int) (blue * a + 0.5);

return 0xff << 24 | red << 16 | green << 8 | blue;

}

/**

* 生成一个和状态栏大小相同的半透明矩形条

*

* @param activity 需要设置的activity

* @param color 状态栏颜色值

* @param alpha 透明值

* @return 状态栏矩形条

*/

private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {

// 绘制一个和状态栏一样高的矩形

View statusBarView = new View(activity);

LinearLayout.LayoutParams params =

new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));

statusBarView.setLayoutParams(params);

statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));

statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);

return statusBarView;

}

/**

* 获取状态栏高度

*

* @param context context

* @return 状态栏高度

*/

public static int getStatusBarHeight(Context context) {

// 获得状态栏高度

int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");

return context.getResources().getDimensionPixelSize(resourceId);

}imageView这种需要填充到状态栏的情况

//重写这个方法

protected void setStatusBar() {

StatusBarUtil.setTransparentForImageView(...);

}

/***

* @param activity 需要设置的activity

* @param needOffsetView 需要向下偏移的 View

*/

public static void setTransparentForImageView(Activity activity, View needOffsetView) {

setTranslucentForImageView(activity, 0, needOffsetView);

}

/*** 为头部是 ImageView 的界面设置状态栏透明

*

* @param activity 需要设置的activity

* @param statusBarAlpha 状态栏透明度

* @param needOffsetView 需要向下偏移的 View

*/

public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,

View needOffsetView) {

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {

return;

}

setTransparentForWindow(activity);

addTranslucentView(activity, statusBarAlpha);

//虽然imageView需要填充到状态栏,但是上面的文字按钮等控件并不需要填充到状态栏,所以需要设置偏移

if (needOffsetView != null) {

Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET);

if (haveSetOffset != null && (Boolean) haveSetOffset) {

return;

}

ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();

layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),

layoutParams.rightMargin, layoutParams.bottomMargin);

needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true);

}

}

/**

* 设置透明

*/

private static void setTransparentForWindow(Activity activity) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

activity.getWindow().setStatusBarColor(Color.TRANSPARENT);

activity.getWindow()

.getDecorView()

//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间

.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

activity.getWindow()

.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

}

}

/**

* 添加半透明矩形条

*

* @param activity 需要设置的 activity

* @param statusBarAlpha 透明值

*/

private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {

ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);

View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);

if (fakeTranslucentView != null) {

if (fakeTranslucentView.getVisibility() == View.GONE) {

fakeTranslucentView.setVisibility(View.VISIBLE);

}

fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));

} else {

contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));

}

}

/**

* 创建半透明矩形 View

*

* @param alpha 透明值

* @return 半透明 View

*/

private static View createTranslucentStatusBarView(Activity activity, int alpha) {

// 绘制一个和状态栏一样高的矩形

View statusBarView = new View(activity);

LinearLayout.LayoutParams params =

new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));

statusBarView.setLayoutParams(params);

statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));

statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID);

return statusBarView;

}**最后小结一下思路:**

首先在基类设置状态栏透明,让contentView填充到状态栏,利用contentView的背景作为状态栏背景直接实现沉浸的效果,然后利用setFitsSystemWindows(true)和setClipToPadding(true)对控件预留出状态栏的位置。

如果需要单独设置状态栏颜色或者透明度,比如contentView的背景色和ActionBar背景不一致的情况,5.0以上通过设置setStatusBarColor实现,4.4-5.0通过伪装状态栏实现。

最后如果需要实现类似图片这种需要填充到状态栏的情况,通过setTransparentForWindow实现,然后对其他控件重设MarginLayoutParams来实现预留出状态栏位置的效果。

经过上面的一些设置已经覆盖了绝大部分情况,对于Fragment,DrawerLayout,CoordinatorLayout等可能需要特殊处理的这里贴上gitgub地址。

**ps:作者不是我,我只是个搬砖的。**

[https://github.com/laobie/StatusBarUtil](https://github.com/laobie/StatusBarUtil)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值