android沉浸式状态栏的适配(包含刘海屏)
写在前面:
1,本文阐述如何实现沉浸式状态栏
2,部分代码有从其他博客摘抄,也有我自己的总结,若侵犯了原作者的权益,请联系我删除
下面说一下我的实现步骤
1,colors
#3F424E #00000000 #FF4081
2,values/styles.xml:
3,values-v19/styles.xml:
4,配置文件使用
5,顶部标题栏,通常我会单独抽出来,关键代码是android:fitsSystemWindows="true"
... ...
6,核心代码(主要来自https://www.jianshu.com/p/a44c119d6ef7,部分是我封装的)
import android.annotation.TargetApi;import android.app.Activity;import android.content.Context;import android.content.res.Resources;import android.os.Build;import android.support.annotation.ColorRes;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;import com.sandy.cloudlock.R;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Properties;public class StatusBarCompatUtil2 { private static final int COLOR_DEFAULT = ResourceUtil.getColor(R.color.colorPrimary); private static int getStatusBarHeight(Context context) { int statusBarHeight = 0; Resources res = context.getResources(); int resourceId = res.getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { statusBarHeight = res.getDimensionPixelSize(resourceId); } return statusBarHeight; } /** * 设置状态栏透明 */ public static void setTranslucentStatus(Activity activity, @ColorRes int statusColor) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = activity.getWindow(); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); int color = COLOR_DEFAULT; if (statusColor != 0) { color = ResourceUtil.getColor(statusColor); } window.setStatusBarColor(color); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int color = COLOR_DEFAULT; ViewGroup contentView = activity.findViewById(android.R.id.content); if (statusColor != 0) { color = ResourceUtil.getColor(statusColor); } View statusBarView = new View(activity); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setBackgroundColor(color); contentView.addView(statusBarView, lp); } else { activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } } /** * 改变魅族的状态栏字体为黑色,要求FlyMe4以上 */ private static void processFlyme(Activity activity, boolean darkMode) { Window window = activity.getWindow(); if (window != null) { try { WindowManager.LayoutParams lp = window.getAttributes(); Field darkFlag = WindowManager.LayoutParams.class .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); Field meizuFlags = WindowManager.LayoutParams.class .getDeclaredField("meizuFlags"); darkFlag.setAccessible(true); meizuFlags.setAccessible(true); int bit = darkFlag.getInt((Object) null); int value = meizuFlags.getInt(lp); if (darkMode) { value |= bit; } else { value &= ~bit; } meizuFlags.setInt(lp, value); window.setAttributes(lp); } catch (Exception var8) { Log.w("StatusBarUtils", "setStatusBarDarkIcon: failed"); } } } /** * 改变小米的状态栏字体颜色为黑色, 要求MIUI6以上 lightStatusBar为真时表示黑色字体 */ private static void processMIUI(Activity activity, boolean darkMode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 即基于 Android 6.0 ,开发版 7.7.13 及以后版本 compatHighMIUI(activity, darkMode); } else { compatLowMIUI(activity, darkMode); } } @TargetApi(Build.VERSION_CODES.M) private static void compatHighMIUI(Activity activity, boolean darkMode) { View decorView = activity.getWindow().getDecorView(); if (darkMode) { decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } else { int flag = decorView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; decorView.setSystemUiVisibility(flag); } } /** * 兼容低版本miui * * @param activity activity * @param darkMode 是否夜间模式 */ private static void compatLowMIUI(Activity activity, boolean darkMode) { Class<? extends Window> clazz = activity.getWindow().getClass(); try { int darkModeFlag = 0; Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); darkModeFlag = field.getInt(layoutParams); Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); extraFlagField.invoke(activity.getWindow(), darkMode ? darkModeFlag : 0, darkModeFlag); } catch (Exception e) { e.printStackTrace(); } } private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code"; private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name"; private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage"; /** * 判断手机是否是小米 */ private static boolean isMIUI() { final Properties prop = new Properties(); return prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null; } /** * 判断手机是否是魅族 * * @return */ private static boolean isFlyme() { try { // Invoke Build.hasSmartBar() final Method method = Build.class.getMethod("hasSmartBar"); return method != null || TextUtils.equals("Meizu", Build.MANUFACTURER); } catch (final Exception e) { return TextUtils.equals("Meizu", Build.MANUFACTURER); } } /** * 设置Android状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色 * * 设置状态栏文字色值为深色调,默认状态栏颜色透明(即同标题栏的颜色) * * @param activity activity * @param useDart 是否使用深色调 */ public static void setStatusBarFontIconDark(Activity activity, boolean useDart) { setStatusBarFontIconDark(activity, useDart, 0); } /** * 设置Android状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色 *
* 设置状态栏文字色值为深色调 * * @param activity activity * @param useDart 是否使用深色调 * @param statusColor 自定义的状态栏颜色 */ public static void setStatusBarFontIconDark(Activity activity, boolean useDart, @ColorRes int statusColor) { if (isMIUI()) { processMIUI(activity, useDart); } else { if (isFlyme()) { processFlyme(activity, useDart); } if (useDart) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int mode = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; activity.getWindow().getDecorView().setSystemUiVisibility(mode); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { int mode = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; activity.getWindow().getDecorView().setSystemUiVisibility(mode); } } activity.getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, 0); } if (statusColor != 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { int color = ResourceUtil.getColor(statusColor); activity.getWindow().setStatusBarColor(color); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ViewGroup contentView = activity.findViewById(android.R.id.content); int color = ResourceUtil.getColor(statusColor); View statusBarView = new View(activity); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setBackgroundColor(color); contentView.addView(statusBarView, lp); } } ///适配虚拟按键背景色// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// activity.getWindow().setNavigationBarColor(COLOR_DEFAULT);// } }}
7,使用
定义1个activity的超类,在超类的onCreate中调用
setStatusBarFontIconDark(Activity activity, boolean useDart)
状态栏颜色自定义,调用
setStatusBarFontIconDark(Activity activity, boolean useDart, @ColorRes int statusColor)
如多个fragment切换时,状态栏颜色不同,可以在fragment的
onActivityCreated (Bundle savedInstanceState)
中调用setStatusBarFontIconDark(Activity activity, boolean useDart, @ColorRes int statusColor)
8,注意:
我手上只有红米3S、荣耀10(刘海屏)、魅蓝E2,这三款机型都能正常适配,其他机型没有测试,如果大家碰到不能适配的,欢迎给我留言
更多相关文章
- 一个android颜色识别器
- Android(安卓)上的调色板 —— Palette
- Android-解决AutoCompleteText下拉提示的字体颜色是白色的问题
- Android(安卓)MPAndroidChart不同区域背景颜色不同,点的颜色不同
- 记一次Android完整项目(1)-设置statusBar颜色
- Android开发小技巧之对android颜色渐变(Gradient )的改进
- Android十六进制透明度代码
- 修改WebView背景颜色为透明
- Android中实现部分字体颜色改变的方式