Android开发 android沉浸式状态栏的适配(包含刘海屏)转载
部分转载原文地址: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沉浸式状态栏的适配(包含刘海屏)转载的更多相关文章
- Android中的沉浸式状态栏效果
无意间了解到沉浸式状态栏,感觉贼拉的高大上,于是就是试着去了解一下,就有了这篇文章.下面就来了解一下啥叫沉浸式状态栏.传统的手机状态栏是呈现出黑色条状的,有的和手机主界面有很明显的区别.这一样就在一定 ...
- Android 4.4沉浸式状态栏的实现
要实现Android 4.4上面的沉浸式状态栏要用到开源项目SystemBarTint(https://github.com/hexiaochun/SystemBarTint) public clas ...
- Android Studio 关于沉浸式状态栏
values-v19/style.xml <style name="AppTheme" parent="Theme.AppCompat.Light.NoAction ...
- [置顶]
Xamarin android沉浸式状态栏
虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...
- android适配pad和部分手机底部虚拟按键+沉浸式状态栏
在使用沉浸式状态栏设置界面全屏时发现pad和部分手机(华为和魅族系统自带)屏幕底部会带有虚拟按键,遮挡住界面本身的一部分. 为了设置隐藏,在网上找了一些方法,设置Activity主题再在布局加fits ...
- Android一体式(沉浸式)状态栏的实现
注:公司开发任务适配是在4.4版本之上进行,所以此适配仅在4.4之上进行测试. 1.主要使用了第三方的开源项目SystemBarTint,github:https://github.com/jgilf ...
- Android 沉浸式状态栏完美解决方案
现在搜索Android 沉浸式状态栏,真的是一堆一堆,写的特别多,但是真正用的舒服的真没有,在这里自己整理一下开发记录 注意,在使用这个步骤过程之前,请把之前设置的代码注释一下 把布局带有androi ...
- 81.Android之沉浸式状态栏攻略
转载:http://blog.csdn.net/lmj623565791/article/details/48649563/ 一.概述 近期注意到QQ新版使用了沉浸式状态栏,ok,先声明一下:本篇博客 ...
- Android App 沉浸式状态栏解决方案
伴随着 Android 5.0 发布的 Material Design,让 Android 应用告别了以前的工程师审美,迎来了全新的界面,灵动的交互,也让越来越多的 App 开始遵从 material ...
随机推荐
- SSH配置
什么是SSH: SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH ...
- ie8的input的placeholder不显示的解决bug
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- HP Elitebook 830 G5/Win10蓝屏 UcmUcsi.sys 错误解决
转自https://support.hp.com/cn-zh/document/c06038185 注意BIOS可能是英文的,别着急,对着找就好了.
- day-13装饰器
函数的嵌套定义 概念:在一个函数的内部定义另一个函数 为什么要有函数的嵌套定义:1)函数fn2想直接使用fn1函数的局部变量,可以将fn2直接定义到fn1的内部,这样fn2就可以直接访问fn1的变量2 ...
- mini-treeselect的动态赋值
<div id="faultTree" allowdrag="false" allowdrop="true" class=" ...
- Python PIL 图像缩小、拼接
比较各种不同取样方式的图像缩放效果. [NEAREST, BILINEAR, BICUBIC, LANCZOS, BOX, HAMMING]NEAREST取样方式是效果最差的,PIL.Image.re ...
- saltstack总结-2018-0620
以下结论 结论1由于minion配置文件里能配置的只有master的IP和master的ret_port,而无法指定master的publish_port因此minion获取的master的publi ...
- ffmpeg-4.1.1-win64-dev在vs2017的搭建
没得话讲,先在官网下载对应的源码,下载dev/文件夹下的源码和静态链接库 ,下载/shared文件夹下的动态链接库 官网地址:https://ffmpeg.zeranoe.com/builds/wi ...
- ubuntu 14.04升级gcc 4.8到5.3
添加PPA库 #sudo apt-get install software-properties-common #sudo add-apt-repository ppa:ubuntu-toolchai ...
- source-insight 常用操作
[Ctrl + ] 跳转到函数.宏.变量 等定义处. [Alt > ] 跳转到最近光标停留位置. [Alt < ] 跳转到上次近光标停留位置. [Ctrl Shift [ ] 块位置开 ...