部分转载原文地址:https://blog.csdn.net/liup1211/article/details/86583015

写在前面:

1,本文阐述如何实现沉浸式状态栏

2,部分代码有从其他博客摘抄,也有我自己的总结,若侵犯了原作者的权益,请联系我删除

下面说一下我的实现步骤

1,colors

    <color name="colorPrimary">#3F424E</color>
<color name="colorPrimaryDark">#00000000</color><!--透明-->
<color name="colorAccent">#FF4081</color>

2,values/styles.xml:

  <style name="AppTheme" parent="AppTheme.Base">

    </style>

    <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">

        <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/default_bg</item>
</style>

3,values-v19/styles.xml:

 <style name="AppTheme" parent="AppTheme.Base">
<!-- Navigation Bar 【false适配某些虚拟按键手机】-->
<item name="android:windowTranslucentNavigation">false</item>
</style>

4,配置文件使用

    <application
... ...
android:theme="@style/AppTheme"
... ...>

5,顶部标题栏,通常我会单独抽出来,关键代码是android:fitsSystemWindows="true"

这是重点,如果不设置android:fitsSystemWindows="true",可能会出现部分机型标题栏显示不全的bug

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"> ... ...

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状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色
* <p>
* 设置状态栏文字色值为深色调,默认状态栏颜色透明(即同标题栏的颜色)
*
* @param activity activity
* @param useDart 是否使用深色调
*/
public static void setStatusBarFontIconDark(Activity activity, boolean useDart) {
setStatusBarFontIconDark(activity, useDart, 0);
} /**
* 设置Android状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色
* <p>
* 设置状态栏文字色值为深色调
*
* @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.问题总结

1.在activity里使用setContentView方法切换了其他layout后android:fitsSystemWindows="true"失效的问题

     Rect rectangle = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);//获取状态栏高度
ConstraintLayout constraintLayout = findViewById(R.id.constraintLayout);//此ConstraintLayout为xml根Layout
constraintLayout.setPadding(0, rectangle.top,0,0);

此方法无奈之举

Android开发 android沉浸式状态栏的适配(包含刘海屏)转载的更多相关文章

  1. Android中的沉浸式状态栏效果

    无意间了解到沉浸式状态栏,感觉贼拉的高大上,于是就是试着去了解一下,就有了这篇文章.下面就来了解一下啥叫沉浸式状态栏.传统的手机状态栏是呈现出黑色条状的,有的和手机主界面有很明显的区别.这一样就在一定 ...

  2. Android 4.4沉浸式状态栏的实现

    要实现Android 4.4上面的沉浸式状态栏要用到开源项目SystemBarTint(https://github.com/hexiaochun/SystemBarTint) public clas ...

  3. Android Studio 关于沉浸式状态栏

    values-v19/style.xml <style name="AppTheme" parent="Theme.AppCompat.Light.NoAction ...

  4. [置顶] Xamarin android沉浸式状态栏

    虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...

  5. android适配pad和部分手机底部虚拟按键+沉浸式状态栏

    在使用沉浸式状态栏设置界面全屏时发现pad和部分手机(华为和魅族系统自带)屏幕底部会带有虚拟按键,遮挡住界面本身的一部分. 为了设置隐藏,在网上找了一些方法,设置Activity主题再在布局加fits ...

  6. Android一体式(沉浸式)状态栏的实现

    注:公司开发任务适配是在4.4版本之上进行,所以此适配仅在4.4之上进行测试. 1.主要使用了第三方的开源项目SystemBarTint,github:https://github.com/jgilf ...

  7. Android 沉浸式状态栏完美解决方案

    现在搜索Android 沉浸式状态栏,真的是一堆一堆,写的特别多,但是真正用的舒服的真没有,在这里自己整理一下开发记录 注意,在使用这个步骤过程之前,请把之前设置的代码注释一下 把布局带有androi ...

  8. 81.Android之沉浸式状态栏攻略

    转载:http://blog.csdn.net/lmj623565791/article/details/48649563/ 一.概述 近期注意到QQ新版使用了沉浸式状态栏,ok,先声明一下:本篇博客 ...

  9. Android App 沉浸式状态栏解决方案

    伴随着 Android 5.0 发布的 Material Design,让 Android 应用告别了以前的工程师审美,迎来了全新的界面,灵动的交互,也让越来越多的 App 开始遵从 material ...

随机推荐

  1. SSH配置

    什么是SSH: SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH ...

  2. ie8的input的placeholder不显示的解决bug

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  3. HP Elitebook 830 G5/Win10蓝屏 UcmUcsi.sys 错误解决

    转自https://support.hp.com/cn-zh/document/c06038185 注意BIOS可能是英文的,别着急,对着找就好了.

  4. day-13装饰器

    函数的嵌套定义 概念:在一个函数的内部定义另一个函数 为什么要有函数的嵌套定义:1)函数fn2想直接使用fn1函数的局部变量,可以将fn2直接定义到fn1的内部,这样fn2就可以直接访问fn1的变量2 ...

  5. mini-treeselect的动态赋值

    <div id="faultTree" allowdrag="false" allowdrop="true" class=" ...

  6. Python PIL 图像缩小、拼接

    比较各种不同取样方式的图像缩放效果. [NEAREST, BILINEAR, BICUBIC, LANCZOS, BOX, HAMMING]NEAREST取样方式是效果最差的,PIL.Image.re ...

  7. saltstack总结-2018-0620

    以下结论 结论1由于minion配置文件里能配置的只有master的IP和master的ret_port,而无法指定master的publish_port因此minion获取的master的publi ...

  8. ffmpeg-4.1.1-win64-dev在vs2017的搭建

    没得话讲,先在官网下载对应的源码,下载dev/文件夹下的源码和静态链接库  ,下载/shared文件夹下的动态链接库 官网地址:https://ffmpeg.zeranoe.com/builds/wi ...

  9. ubuntu 14.04升级gcc 4.8到5.3

    添加PPA库 #sudo apt-get install software-properties-common #sudo add-apt-repository ppa:ubuntu-toolchai ...

  10. source-insight 常用操作

    [Ctrl + ] 跳转到函数.宏.变量 等定义处. [Alt  > ] 跳转到最近光标停留位置. [Alt  < ] 跳转到上次近光标停留位置. [Ctrl Shift [ ] 块位置开 ...