Android状态栏适配问题

Android状态栏适配是一个老生常谈的问题,那么我又拿出来讲了,因为这个东西确实太重要了,基本上每个项目都用得到。状态栏总共有几种形态。第一,让状态栏颜色跟应用主色调一致,布局内容不占有状态栏的位置。第二,让布局内容的顶部成为状态栏的一部分,状态栏透明。第三,有DrawerLayout的情况,侧边栏滑出来,一半侧边栏的顶部界面,一半内容的顶部界面,且不透明。

让状态栏颜色跟应用主色调一致,布局内容不占有状态栏的位置

设置非全屏的状态栏颜色

/**
 * 设置不全屏内容的状态栏颜色。
 *
 * @param activity       需要设置的activity
 * @param statusBarColor 状态栏颜色值
 * @param statusBarAlpha 状态栏透明度
 */
public static void setStatusBar(Activity activity, @ColorInt int statusBarColor, @IntRange(from = 0, to = 255) int statusBarAlpha) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // >= 6.0 支持根据状态栏颜色定制浅色和深色的文字和图标
        activity.getWindow().setStatusBarColor(statusBarColor);
        int option;
        if (isDarkColor(statusBarColor)) {
            // 深色状态栏,则让状态栏文字和图标变白
            option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
        } else {
            // 浅色状态栏,则让状态栏文字和图标变黑
            option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
        }
        activity.getWindow().getDecorView().setSystemUiVisibility(option);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // 5.x
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        activity.getWindow().setStatusBarColor(calculateColor(statusBarColor, statusBarAlpha));
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 4.4 自己创建一个色块加到DecorView
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        View doraStatusBarView = decorView.findViewById(DORA_STATUS_BAR_VIEW_ID);
        if (doraStatusBarView != null) {
            if (doraStatusBarView.getVisibility() == View.GONE) {
                doraStatusBarView.setVisibility(View.VISIBLE);
            }
            doraStatusBarView.setBackgroundColor(calculateColor(statusBarColor, statusBarAlpha));
        } else {
            decorView.addView(createStatusBarView(activity, statusBarColor, statusBarAlpha));
        }
        setFitsSystemWindow(activity);
    } else {
        // < 4.4 不可定制,黑色状态栏,无解
    }
}

检测状态栏的颜色,以确定用深色还是浅色的文字和图标

/**
 * 状态栏是否是深色。
 *
 * @param color 状态栏颜色值
 */
public static boolean isDarkColor(@ColorInt int color) {
    int gray = (int) (Color.red(color) * 0.299 + Color.green(color) * 0.587 + Color.blue(color) * 0.114);
    return gray >= 192;
}

自己创建一个和状态栏一样高度的色块。

/**
 * 生成一个和状态栏大小相同的矩形条。
 *
 * @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(calculateColor(color, alpha));
    statusBarView.setId(DORA_STATUS_BAR_VIEW_ID);
    return statusBarView;
}

根布局设置fitsSystemWindow

private static void setFitsSystemWindow(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);
        }
    }
}

获取状态栏的高度

private static int getStatusBarHeight(Context context) {
    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    return context.getResources().getDimensionPixelSize(resourceId);
}

计算带透明度后的颜色

private static int calculateColor(@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;
}

让布局内容的顶部成为状态栏的一部分,状态栏透明

public static void setFullScreenStatusBar(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);
        activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    } else {
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
    activity.getWindow()
            .getDecorView()
            .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

DrawerLayout设置状态栏颜色

设置DrawerLayout的状态栏一半的颜色

public static void setStatusBar(Activity activity, DrawerLayout drawerLayout, @ColorInt int statusBarColor,
                                @IntRange(from = 0, to = 255) int statusBarAlpha) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return;
    }
    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.TRANSPARENT);
    } else {
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
    ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
    View doraStatusBarView = contentLayout.findViewById(DORA_STATUS_BAR_VIEW_ID);
    if (doraStatusBarView != null) {
        if (doraStatusBarView.getVisibility() == View.GONE) {
            doraStatusBarView.setVisibility(View.VISIBLE);
        }
        doraStatusBarView.setBackgroundColor(statusBarColor);
    } else {
        contentLayout.addView(createStatusBarView(activity, statusBarColor), 0);
    }
    if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
        contentLayout.getChildAt(1)
                .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
                        contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
    }
    setFitsSystemWindow(drawerLayout, contentLayout);
    addStatusBarView(activity, statusBarAlpha);
}

设置fitsSystemWindow

private static void setFitsSystemWindow(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) {
    ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
    drawerLayout.setFitsSystemWindows(false);
    drawerLayoutContentLayout.setFitsSystemWindows(false);
    drawerLayoutContentLayout.setClipToPadding(true);
    drawer.setFitsSystemWindows(false);
}

添加状态栏View

/**
 * 添加半透明矩形条。
 *
 * @param activity       需要设置的 activity
 * @param statusBarAlpha 状态栏透明度
 */
private static void addStatusBarView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
    ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
    View doraStatusBarView = contentView.findViewById(DORA_STATUS_BAR_VIEW_ID);
    if (doraStatusBarView != null) {
        if (doraStatusBarView.getVisibility() == View.GONE) {
            doraStatusBarView.setVisibility(View.VISIBLE);
        }
        doraStatusBarView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
    } else {
        contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
    }
}
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dora丶Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值