react-native android状态栏的实现


Posted in Javascript onJune 15, 2018

react-native 开发App的时候难免会遇到状态栏的,背景颜色和字体颜色与App内容页面,色调适配,间言之就是将状态栏颜色与App颜色一致,使用户界面更加整体。

1.android设备系统元素

  1. 导航栏:就是设备顶部的网络、时间、电量等信息栏
  2. ActionBar: 返回按钮以及系统默认的header区域,RN开发中一般不会用到,RN中在navigation中进行定制
  3. 导航栏: 设备下方的物理返回、回桌面、选择应用程序等系统导航栏

2.状态栏的呈现形式

  1. 默认展示,一直显示手机系统的状态栏
  2. 透明状态栏,状态栏背景颜色透明,状态栏颜色与App颜色一致,用户界面更加整体。
  3. 隐藏状态栏(沉浸式),状态栏完全隐藏,类似于全屏游戏、视频播放器的效果

2.1 默认展示

系统默认状态栏样式,无法改变

2.2 透明状态栏

透明状态栏很常见,大多数的App都是使用这种模式,使得状态栏颜色与App颜色一致,使用户界面更加整体,整个应用看起来更加美观。

实现透明的状态栏的方式很多:

一、使用App的主题进行配置,在app/main/res/values/styles.xml中设置主题

<resources>

 <!-- Base application theme. -->
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="android:windowTranslucentStatus">true</item> // 设置状态栏不占据空间
  // <item name="android:windowLightStatusBar">true</item> // 设置状态栏字体颜色
 </style>

</resources>

这种方式支持api19, 即Android4.4及以上,会在App启动的时候就生效, 在App启动时有权限确认、系统弹窗等也不受影响,在弹出modal之类的深色蒙层时状态栏字体会变成成浅色

只设置 <item name="android:windowTranslucentStatus">true</item> 这种方式设置的透明状态栏,状态栏字体默认白色,无法再动态通过StatusBar改变状态栏的背景颜色,在做需要改变状态栏背景颜色的时候就比较尴尬了

再加一个 <item name="android:windowLightStatusBar">true</item> 这样设置状态栏字体颜色之后,在深色modal弹出的时候字体不会动态改变成白色,但可以通过StatusBar设置barStyle来改变,实际上也不是很方便

二、android原生设置,在MainActivity的onCreate中进行设置

protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 // 设置透明状态栏
 if (Build.VERSION.SDK_INT >= 21) {
  View decorView = getWindow().getDecorView();
  int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  decorView.setSystemUiVisibility(option);
  getWindow().setStatusBarColor(Color.TRANSPARENT);
 }
 
 // 设置透明状态栏和透明导航栏
 if (Build.VERSION.SDK_INT >= 21) {
  View decorView = getWindow().getDecorView();
  int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  decorView.setSystemUiVisibility(option);
  getWindow().setNavigationBarColor(Color.TRANSPARENT);
  getWindow().setStatusBarColor(Color.TRANSPARENT);
 }
}

透明式状态栏,只有5.0及以上系统才支持,因此这里先进行了一层if判断,只有系统版本大于或等于5.0的时候才会执行下面的代码。 接下来我们使用了 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN SYSTEM_UI_FLAG_LAYOUT_STABLE ,注意两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间,也就是说状态栏不再占据空间。最后再调用Window的setStatusBarColor()方法将状态栏设置成透明色就可以了。

三、使用RN的StatusBar来设置,在App首次加载的页面中对状态栏进行设置

<StatusBar backgroundColor='transparent' translucent barStyle={'dark-content'} />

这种方式,会在App刚启动的时候和App启动时有权限确认、系统弹窗等会先试用系统的默认状态栏,加载App页面之后再改变成上面设置的样式。 好处在于可以动态进行设置状态栏的样式。

StatusBar属性简介:

  1. animated: bool 指定状态栏的变化是否应以动画形式呈现。目前支持这几种样式:backgroundColor, barStyle和hidden
  2. hidden: bool 是否隐藏状态栏。
  3. backgroundColor: 状态栏的背景色。
  4. translucent: bool 指定状态栏是否透明。设置为true时,应用会在状态栏之下绘制(即所谓“沉浸式”——被状态栏遮住一部分)。常和带有半透明背景色的状态栏搭配使用。
  5. barStyle: enum('default', 'light-content', 'dark-content') 设置状态栏文本的颜色。

以上几种方式都会有一个问题,状态栏不再占据空间,因此在页面布局的时候需要加 paddingTop 值为状态栏的高度。

纯前端就可以实现,这也是适配目前主流刘海屏的一种方式,利用StatusBar.currentHeight可以获取到设备状态栏的高度。

2.3 隐藏 状态栏 和 导航栏

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

3. 浅色状态栏的兼容性配置

目前市面上的浅色状态栏基本都是 白底黑字, 支持这种设置的有Android6.0及其以上; MIUI v6及以上, Flyme 4.0及以上

具体兼容方案如下:

Flyme 4.0及以上

public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
 boolean result = false;
 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(null);
   int value = meizuFlags.getInt(lp);
   if (dark) {
    value |= bit;
   } else {
    value &= ~bit;
   }
   meizuFlags.setInt(lp, value);
   window.setAttributes(lp);
   result = true;
  } catch (Exception e) {

  }
 }
 return result;
}

Android6.0及以上

public static void setAndroidNativeLightStatusBar(Activity activity, boolean dark) {
 //状态栏字体图标颜色
 View decor = activity.getWindow().getDecorView();
 if (dark) {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR //浅色状态栏(字体图标白色)
     | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //contentView 全屏(置于statusbar之下)
     | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
  }
 } else {
  decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
 }
}

MIUI v6及以上

public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
 if(Build.VERSION.SDK_INT >= 24){
  return false;
 }
 boolean result = false;
 Window window=activity.getWindow();
 if (window != null) {
  Class clazz = window.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);
   if(dark){
    extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
   }else{
    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
   }
   result=true;

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
    if(dark){
     activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }else {
     activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    }
   }
  }catch (Exception e){

  }
 }
 return result;
}

在MainActivity的onCreate中调用

LightStatusBarUtil.FlymeSetStatusBarLightMode(this.getWindow(), false);
LightStatusBarUtil.MIUISetStatusBarLightMode(this, false); 
LightStatusBarUtil.setAndroidNativeLightStatusBar(this, true);

总结

实现透明状态栏,以上方案都没有完全兼容android 4.4以下版本,个人觉得比较合适的做法是 android设置透明状态栏 + 浅色状态栏的兼容性配置 + StatusBar 来配合控制

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点)
Mar 10 Javascript
收藏Javascript中常用的55个经典技巧
Aug 12 Javascript
js实现数字每三位加逗号的方法
Feb 05 Javascript
JavaScript中的分号插入机制详细介绍
Feb 11 Javascript
javascript下使用Promise封装FileReader
Feb 19 Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
May 03 Javascript
AngularJs解决跨域问题案例详解(简单方法)
May 19 Javascript
Javascript获取随机数的实现方法
Jun 22 Javascript
js中class的点击事件没有效果的解决方法
Oct 13 Javascript
在网页中插入百度地图的步骤详解
Dec 02 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
实现Vue的markdown文档可以在线运行的方法示例
Dec 11 Javascript
JS实现监控微信小程序的原理
Jun 15 #Javascript
vue .sync修饰符的使用详解
Jun 15 #Javascript
vue项目webpack中Npm传递参数配置不同域名接口
Jun 15 #Javascript
vue和webpack项目构建过程常用的npm命令详解
Jun 15 #Javascript
vue和webpack安装命令详解
Jun 15 #Javascript
Webpack devServer中的 proxy 实现跨域的解决
Jun 15 #Javascript
详解webpack的proxyTable无效的解决方案
Jun 15 #Javascript
You might like
php的sprintf函数的用法 控制浮点数格式
2014/02/14 PHP
php基于str_pad实现卡号不足位数自动补0的方法
2014/11/12 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
Laravel 5框架学习之表单验证
2015/04/08 PHP
php实现自定义中奖项数和概率的抽奖函数示例
2017/05/26 PHP
4种Windows系统下Laravel框架的开发环境安装及部署方法详解
2020/04/06 PHP
如何在Laravel之外使用illuminate组件详解
2020/09/20 PHP
根据判断浏览器类型屏幕分辨率自动调用不同CSS的代码
2007/02/22 Javascript
jquery的ajaxSubmit()异步上传图片并保存表单数据演示代码
2013/06/04 Javascript
jquery复选框全选/取消示例
2013/12/30 Javascript
如何使用jquery easyui创建标签组件
2015/11/18 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
javascript弹出带文字信息的提示框效果
2016/07/19 Javascript
前端JS面试中常见的算法问题总结
2016/12/23 Javascript
详解AngularJS 模块化
2017/06/14 Javascript
JS实现新建文件夹功能
2017/06/17 Javascript
详解如何使用 vue-cli 开发多页应用
2017/12/16 Javascript
对vue 键盘回车事件的实例讲解
2018/08/25 Javascript
vue结合element-ui使用示例
2019/01/24 Javascript
微信小程序学习笔记之本地数据缓存功能详解
2019/03/29 Javascript
ES6中异步对象Promise用法详解
2019/07/31 Javascript
vue实现lodop打印功能的示例
2020/11/11 Javascript
[08:44]和酒神一起战斗 DOTA2教你做大人
2014/03/27 DOTA
使用Python从零开始撸一个区块链
2018/03/14 Python
django 发送邮件和缓存的实现代码
2018/07/18 Python
python实现简单http服务器功能
2018/09/17 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
Python3 元组tuple入门基础
2020/02/09 Python
基于spring boot 日志(logback)报错的解决方式
2020/02/20 Python
CPB肌肤之钥美国官网:Clé de Peau Beauté
2017/09/05 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
旅游网创业计划书
2014/01/31 职场文书
充分就业社区汇报材料
2014/05/07 职场文书
党的群众路线教育实践活动个人对照检查材料(四风)
2014/11/05 职场文书
反邪教观后感
2015/06/11 职场文书
HTTP中的Content-type详解
2022/01/18 HTML / CSS