美文网首页
React-native android 启动屏

React-native android 启动屏

作者: 马六甲的笔记 | 来源:发表于2020-03-14 23:36 被阅读0次

    前言

    android 启动时会使用一个 白色 或 黑色 的启动背景,在 app 界面成功加载后,启动背景被 app 界面覆盖。

    若 app 启动时,没有什么耗时的异步操作,可以秒载入界面,那么就没必要继续往下看了,因为没必要再弄一个启动屏耽误事,但如果启动后需要初始化一些信息才能显示界面,期望在异步载入时显示一个自定义欢迎屏,请继续

    方案一

    做一个静态 activey 欢迎页,启动后立即显示这个,待实际界面准备好之后,替换这个 activey 为实际界面,比如 react-native-splash-screen 就是采用的这种方案。

    但这带来一个问题,就是这个欢迎页本身的绘制也需要时间,虽然非常快,但启动时第一眼看到的仍然会是一闪而过的启动背景,即白屏。消除这个白屏可以在 android/app/src/main/res/values/styles.xml 进行样式设置(下面是 RN 的 theme)

    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
             .....
             <!--启动背景改为透明-->
             <item name="android:windowIsTranslucent">true</item>
        </style>
    </resources>
    

    经过上面的修改,没有启动白屏了,但会发现,点击 app 图标后,会有一下停顿感,然后显示欢迎屏。其实很好理解,这个停顿感其实就是正在显示透明的启动背景,等同于把白屏体验改为停顿感了。

    方案二

    既然 app 启动瞬间显示的是启动背景,那么直接美化启动背景,当做欢迎屏不就可以了嘛。

    同样是修改 android/app/src/main/res/values/styles.xml,改为下面这样

    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            ...
            <!--设置启动背景为一个资源文件-->
            <item name="android:windowBackground">@drawable/splash</item>
        </style>
    </resources>
    

    创建启动背景资源文件 @drawable/splash,保存路径为 android/app/src/main/res/drawable/splash.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item><color android:color="#ffffff"/></item>
        <item>
            <bitmap android:src="@drawable/splash_img"
                android:antialias="true"
                android:filter="true"
                android:gravity="center" />
        </item>
    </layer-list>
    

    启动背景资源文件解释:

    1. 第一个 item 设置背景,因为 android 有众多分辨率,不可能启动背景图刚好覆盖满,所以图片的边缘最好是纯色,通过设置背景颜色自动衔接即可。

    2. @drawable/splash_img 指定启动背景图,参考 android不同分辨率适配drawable 文件可以创建一个,也可以创建多个,当屏幕分辨率对上号了,优先使用最匹配的 drawable,若匹配不上,则选用最接近的一个,并按照比例进行缩放;

      一般情况下,只需针对最大像素密度(当前为 drawable-xxhdpi)制作一张图片即可,当用户分辨率小时,会使用该图片并自动按照像素密度缩小,可能导致图片锐化。可以测试一下,如果锐化导致图片过于失真,可考虑多制作几张,如 drawable/splash_img.pngdrawable-hdpi/splash_img.png 等等;

    3. Bitmap配置,可根据文档自行调整图片位置;若碰到较为复杂的启动屏,单纯一张图不好搞时,可看看九宫格类型图片(NinePatchXml.9图片) 是否可实现需求。

    React-Native JS 端

    以上是 android 启动背景配置,不是针对 RN 的,只要是 android 项目都适合;

    最后说一下 RN 的 JS 部分,一般情况下,我们会在 app 启动时,初始化一些东西,期望在初始化完成前,持续显示启动屏,那么只需要在入口 app.js 完成初始化之后再渲染界面即可,代码示例:

    export default class extends React.Component {
      state = {
        ready: false
      }
    
      componentDidMount() {
          // 执行完异步任务后, 开始绘制
          doAsyncWork().then(() => {
             this.setState({
                ready:true
             });
          })
      }
    
      render(){
        if (!this.state.ready) {
          return null;
        }
        return <View/>;
      }
    }
    

    番外:启动配置

    • 上面的配置为最简化配置,启动背景将显示在 【顶部状态】 与 【底部虚拟导航栏】 之间;
    • 其中底部虚拟导航栏可能没有,比如之前的手机是物理导航键,新的全面屏手机,但这都不影响适配,启动背景肯定在可用区域内。
    • 若想针对性优化,需考虑状态栏和导航栏:文字是深色/浅色、背景是纯色/半透明/完全透明、状态栏是否下沉为沉浸式、导航栏区域是否为沉浸式

    以下是实测结果:

    • 无 API 版本限制的在 android/app/src/main/res/values/styles.xml 中配置即可
    • 有 API 版本限制,比如最低 API Level 19,在 android/app/src/main/res/values-v19/styles.xml 中配置
    • 如 API Level 19 仍需要通用配置的话,需将配置从 /values/styles.xml 复制到 values-v19/styles.xml,换句话说,每个配置都是独立的,而不是继承。
    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    
              <!--
                  通用: 全屏显示,状态栏不显示,启动背景显示到最顶端。
                 但对于有刘海屏的机器,状态栏会变成一个大黑边,无字
                 对于有虚拟导航栏的手机,虚拟导航栏以浮动的状态位于底部,
                 即启动背景最下方会被导航栏覆盖
              -->
              <item name="android:windowFullscreen">true</item>
    
               <!--
                  API 28:  在  windowFullscreen 开启后,通过该设置可去除刘海屏手机顶部的大黑边
                 启动背景将显示到手机的最顶端。
               -->
              <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
              
               <!--
                  API 21:  在  windowFullscreen 开启后,通过该属性设置为 false
                 启动背景最低端 为 导航栏上沿,即导航栏不会覆盖启动背景了
                 低版本无法使用,不过低版本 android 那会,好像还没有虚拟导航栏
               -->
              <item name="android:windowDrawsSystemBarBackgrounds">false</item>
    
    
    
    
              <!--
                  API 19:  状态栏/虚拟导航栏 半透明,开启后,将以半透明背景的状态浮动在顶/底部
                  1. 不能与 windowFullscreen=true 同时使用,因为状态直接不显示了,该设置无意义
                  2. 对于有刘海屏的,状态栏与刘海齐平,启动背景显示在状态栏(包括刘海)下方
                  3. 不支持 windowDrawsSystemBarBackgrounds 设置,启动背景总是铺满全屏
               -->
             <item name="android:windowTranslucentStatus">true</item>
             <item name="android:windowTranslucentNavigation">true</item>
    
       
              <!--
                  API 21:  状态栏/虚拟导航栏 完全透明
                  1. 同样的,不能与 windowFullscreen=true 同时使用,理由同上
                  2. 也不能与 windowTranslucentStatus / windowTranslucentNavigation 同时使用
                       优先级低于上述属性,同时使用,这里将不生效
                  3. 对于有刘海屏的,刘海区域也属于启动背景的可用区域,即启动背景铺满全屏
               -->
             <item name="android:statusBarColor">@android:color/transparent</item>
             <item name="android:navigationBarColor">@android:color/transparent</item>
    
    
               <!--
                  API 23 / 27:  状态栏/虚拟导航栏 是否启用浅色模式(指背景浅色),文字为深色
                  1. windowLightStatusBar 要求 API 23,windowLightNavigationBar 要求 API 27
                  2. 使用半透明 状态栏/导航栏 ,该设置没什么必要性
                  3. 使用完全透明的 状态栏/导航栏, 可根据启动背景色调进行设置
               -->
              <item name="android:windowLightStatusBar">true</item>
              <item name="android:windowLightNavigationBar">true</item>
    
        </style>
    </resources>
    

    推荐配置

    1. /values/styles.xml 中仅设置启动背景就好了,兼容特低版本
    2. /values-v19/styles.xml:Android4.4 以上,支持状态栏半透明
    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            ...
            <item name="android:windowBackground">@drawable/splash</item>
            <item name="android:windowTranslucentStatus">true</item>
        </style>
    </resources>
    
    1. 让状态栏完全透明,根据启动背景色调。
      如果是深色, /values-v21/styles.xml: Android5.0 以上,状态栏背景完全透明,文字为浅色
    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            ...
            <item name="android:windowBackground">@drawable/splash</item>
            <item name="android:statusBarColor">@android:color/transparent</item>
        </style>
    </resources>
    

    如果是浅色,/values-v23/styles.xml: Android6.0 以上,状态栏背景完全透明,文字为深色

    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            ...
            <item name="android:windowBackground">@drawable/splash</item>
            <item name="android:statusBarColor">@android:color/transparent</item>
            <item name="android:windowLightStatusBar">true</item>
        </style>
    </resources>
    

    虚拟导航栏没什么必要去处理,一是因为那里并不影响美观,二是因为全面屏手机越来越多。

    相关文章

      网友评论

          本文标题:React-native android 启动屏

          本文链接:https://www.haomeiwen.com/subject/raivshtx.html