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 ...
随机推荐
- 虚函数表:QT5与VS2015的差异
问题原自下面一段代码: 初学C++虚函数表时,以下代码在QT和VS(版本如题)编译结果不同. #include <iostream> using namespace std; class ...
- Buy or Build(UVa1151)
如果枚举每个套餐,并每次都求最小生成树,总时间复杂度会很高,因而需要先求一次原图的最小生成树,则枚举套餐之后需要考虑的边大大减少了. 具体见代码: #include<cstdio> #in ...
- Appium环境搭建——安卓真机调试注意点
1.安卓设备连接失败 通过adb devices命令 查看安卓设备的连接情况,如图,未成功连接 解决方法: (1)关闭360安全卫士和360手机助手(2)查看5037端口是否被占用 netstat - ...
- Python基础:九、运算符
一.赋值运算 简单的赋值运算符号:= c = a + b #将a+b的元算结果赋值给c 加法赋值运算符:+= c += a #等效于 c = c + a 减法赋值运算符:-= c -= a #等效于 ...
- 将TUM数据集的RGB-D数据集转化为klg格式
1.在github上下载代码png_to_klg git clone https://github.com/HTLife/png_to_klg 2.将png_to_klg目录下的associate.p ...
- C# DataView数据处理的几种方法
1.找到刚删除的所有列 DataView dv = dt.DefaultView; dv.Delete(); dv.Delete(); //找出所有刚删除掉的行 1.5 dv.RowStateFilt ...
- mybatis 中javaType和OfType 的区别
JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型.pojo类: publiccla ...
- 【Python】SciKit-Learn包安装问题
pip install scikit-learn 如果失败的话,可以考虑直接升级pip 我原先的pip版本是10.0.1 安装失败 升级pip到18.1后,在安装就成功了
- linux下tomcat启动慢解决方法
前言 最近在工作中遇到一个问题,在Linux下Tomcat 8启动很慢,且日志上无任何错误,在日志中查看到如下信息: Log4j:[2017-08-2715:47:11] INFO ReadPrope ...
- 定时任务模块 schedule
# coding:utf-8 from learning_python.Telegram_push.check_hardware import check_cpu import schedule im ...