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 ...
随机推荐
- Css新增内容
css3新增属性 可节省设计时间的属性 border-color:控制边框的颜色,并且有更大的灵活性,可以产生渐变效果 border-image:控制边框图像 border-radius:能产生类似圆 ...
- 解题报告 『宝藏(Prim思想 + 访问顺序随机)』
原题地址 本以为不过是一道Prim算法模版题,但貌似只能得45分,虽然对我这种蒟蒻来说已经够了. 然而同机房大佬表示可以用模拟退火A了此题,遂习之,终无所获. 然而机缘巧合之下习得了另一种随机算法,于 ...
- Alpha阶段个人心得
在一个学期的学习中,我从一个只会一个人打打小规模代码的初学者也变成了一个能参与到团队做项目的“入门码农”,而我们团队从一开始对大型项目的望而生畏无从下手变成细分任务各司其职,也了解并感受到github ...
- 发送ajax步骤
1.创建异步对象 一般命名为xhr var xhr = new XMLHttpRequest(); 2. 设置请求行 open(请求方式,请求url) 1.get 需要在url后 ...
- 【分布式锁】redis实现
转载:https://www.jianshu.com/p/c970cc710SETNX命令简介 SETNX key value 将key的值设为value,并且仅当key不存在. 若给定的key已经存 ...
- SpeedReader for Mac(快速阅读器)v1.6免费版
SpeedReader for Mac是一款运行在Mac平台上的阅读软件,通过这款软件就可以自行调整阅读速度.通过SpeedReader Mac版用户可以将想要阅读的内容拖入到软件中,调整速度和字体, ...
- HBASE 优化之REGIONSERVER
HBASE 优化之REGIONSERVER 一,概述 本人在使用优化regionserver的过程有些心得,借此随笔的机会,向大家介绍我的心得,有些是网上拿来的有些是自己在使用过程自己的经验,希望对大 ...
- mysql 高版本only_full_group_by 错误
[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated c ...
- Pyhon 逻辑运算符
- python selenium 处理时间日期控件(十六)
测试过程中经常遇到时间控件,需要我们来选择日期,一般处理时间控件通过层级定位来操作或者通过调用js来实现. 1.首先我们看一下如何通过层级定位来操作时间控件. 通过示例图可以看到,日期控件是无法输入日 ...