部分转载原文地址: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. jmeter脚本录制与性能指标分析

    一.浏览器代理设置(猎豹) 1.打开猎豹浏览器,进行如下图操作 2.点击局域网设置 3.输入如下信息,注意端口不要重复 4.输入网址www.baidu.com,不能正常访问就是正确的 5.查看添加的端 ...

  2. PAT乙级考前总结(三)

    特殊题型 1027 打印沙漏 (20 分) 题略,感觉有点像大学里考试的题.找规律即可. #include <stdio.h>#include <iostream>using ...

  3. 使用maven整合spring+springmvc+mybatis

    使用maven整合spring+springmvc+mybatis 开发环境: 1. jdk1.8 2. eclipse4.7.0 (Oxygen) 3. mysql 5.7 在pom.xml文件中, ...

  4. 学习笔记CB004:提问、检索、回答、NLPIR

    聊天机器人,提问.检索.回答. 提问,查询关键词生成.答案类型确定.句法和语义分析.查询关键词生成,提问提取关键词,中心词关联扩展词.答案类型确定,确定提问类型.句法和语义分析,问题深层含义剖析.检索 ...

  5. 学习笔记TF063:TensorFlow Debugger

    TensorFlow Debugger(tfdbg),TensorFlow专用调试器.用断点.计算机图形化展现实时数据流,可视化运行TensorFlow图形内部结构.状态.有助训练推理调试模型错误.h ...

  6. freebsd 记录点

    问题一: FreeBSD修改python的默认版本 在/usr/local/bin目录下, mv python python.old ln -s pythonX.X  python in X.X wr ...

  7. intval — 获取变量的整数值

    echo intval ( '-42' ); // -42

  8. Day 22 初识面向对象

    一.两种编程思想 1.面向过程编程 核心是'过程',过程指的是解决问题的步骤,就是先干什么再干什么 基于面向过程思想编写程序相当于写一条流水线,是一种机械式的思维方式 优点:解决问题的思路清晰,可以把 ...

  9. eclipse中解决git分支合并冲突

    冲突场景: 在master分支上有文件student.py. 在master上增新一个dev分支 在dev分支上修改文件student.py.增加函数def d():,并commit; 在master ...

  10. win7和linux下利用命令查看文件md5、sha1、sha256

    win7 certutil -hashfile <filename> MD5 certutil -hashfile <filename> SHA1 certutil -hash ...