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 相关文章推荐
JS option location 页面跳转实现代码
Dec 27 Javascript
js操作select控件的几种方法
Jun 02 Javascript
JavaScript 的继承
Oct 01 Javascript
javascript ajax 仿百度分页函数
Oct 29 Javascript
Jquery取得iframe下内容的方法
Nov 18 Javascript
jQuery中odd选择器的定义和用法
Dec 23 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
Jan 13 Javascript
Vue调试神器vue-devtools安装方法
Dec 12 Javascript
JS判断用户用的哪个浏览器实例详解
Oct 09 Javascript
jquery无缝图片轮播组件封装
Nov 25 jQuery
微信小程序如何获取群聊的openGid以及名称详解
Jul 17 Javascript
vue element-ui实现动态面包屑导航
Dec 23 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如何抛出异常处理错误
2011/03/02 PHP
新浪的图片新闻效果
2007/01/13 Javascript
JavaScript 中的事件教程
2007/04/05 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
2011/12/11 Javascript
js中typeof的用法汇总
2013/12/12 Javascript
javascript引用赋值(地址传值)用法实例
2015/01/13 Javascript
基于javascript实现九宫格大转盘效果
2020/05/28 Javascript
JQuery Mobile 弹出式登录框的实现方法
2016/05/28 Javascript
JS常用字符串方法(推荐)
2021/01/15 Javascript
基于JSON格式数据的简单jQuery幻灯片插件(jquery-slider)
2016/08/10 Javascript
走进AngularJs之过滤器(filter)详解
2017/02/17 Javascript
Vuex 快速入门(简单易懂)
2018/09/20 Javascript
详解Webpack loader 之 file-loader
2018/11/07 Javascript
微信小程序select下拉框实现效果
2019/05/15 Javascript
Centos Python2 升级到Python3的简单实现
2016/06/21 Python
分析Python中解析构建数据知识
2018/01/20 Python
图解Python变量与赋值
2018/04/03 Python
Python实现的txt文件去重功能示例
2018/07/07 Python
Numpy 改变数组维度的几种方法小结
2018/08/02 Python
Python SQL查询并生成json文件操作示例
2018/08/17 Python
Python正则匹配判断手机号是否合法的方法
2020/12/09 Python
Python实现的多进程拷贝文件并显示百分比功能示例
2019/04/09 Python
Python字符串大小写转换拼接删除空白
2019/09/19 Python
python如何获取apk的packagename和activity
2020/01/10 Python
python Canny边缘检测算法的实现
2020/04/24 Python
Django 解决新建表删除后无法重新创建等问题
2020/05/21 Python
Python如何读取、写入JSON数据
2020/07/28 Python
opencv python 对指针仪表读数识别的两种方式
2021/01/14 Python
使用CSS3制作版头动画效果
2020/12/24 HTML / CSS
阿里巴巴Oracle DBA笔试题答案-备份恢复类
2013/11/20 面试题
技术总监管理职责范本
2014/03/06 职场文书
培训科主任岗位职责
2014/08/08 职场文书
2014离婚协议书范文
2014/09/10 职场文书
中秋节祝酒词
2015/08/12 职场文书
送给客户微信问候语!
2019/07/04 职场文书
Python中的tkinter库简单案例详解
2022/01/22 Python