React Native 实现无白屏启动页
一个 React Native 应用在启动的时候往往不如原生快,这主要是因为 RN 比原生应用多了一层 JS Bridge,需要的初始化的时间也就更长一些。所以如果不做任何改动的话,我们打开应用的瞬间就会观察到短暂的白屏现象。为了更好的用户体验,我们需要想办法去掉这个讨厌的白屏,使得应用在打开时就显示启动页。
本文主要讨论如何使用 react-native-splash-screen 在 Android 和 iOS 上实现无白屏启动页效果。
Android 上启动页的实现
现有方案的对比
通常,在 Android 上,我们会为启动页设置以下 Theme:
1 |
|
通过添加 android:windowBackground
来设置启动页背景图,然后再在 SplashScreenActivity 中做路由跳转。但是这在 RN 中显然行不通,因为 RN 里只有一个 MainActivity
。
网上的文章中,有一种方案是通过自己配置一个启动页 activity,在其中对 ReactRootView
以及 ReactInstanceManager
进行预加载,加载完毕后再跳转到 MainActivity
。这种做法会有一些副作用,而且也并非完美的解决方案,需要对 ReactActivityDelegate
和 ReactActivityDelegate
进行改造。
react-native-splash-screen 的作者提供了一种思路,只要在根视图上添加一个 dialog 遮盖掉白屏,然后等到合适的时机(JS Bundle 加载并渲染完毕后)再隐藏掉这个 dialog。
这种方法还是非常巧妙的,因为我们不需要对源码做修改,所以不用担心随着 RN 版本的迭代更新而失效,而且也不会对 RN 组件的生命周期造成影响。
Android 实现细节
安装 react-native-splash-screen 之后,我们需要添加一个开屏页的布局 launch_screen.xml
,理论上来说可以自由添加任何元素,但是不推荐添加过于复杂的布局,一般来说添加一张图片就足够了:
1 |
|
之后我们还可以定制化开屏页的主题,如下:
1 |
|
这里有两种选项,一种是直接跳过冷启动的白屏,另一种是替换默认背景图,推荐使用第二种方式。
然后将主题应用到开屏页:
1 |
|
这里我将开屏页的主题和 App 主题设置为同一个,这样状态栏颜色就不会发生变化。因为我发现如果开屏页和 App 主题的状态栏颜色不一致的话,会造成启动时状态栏从 App 主题颜色过渡到启动页状态栏颜色,进入主页面后再过渡到 App 主题,效果不是很好。
看下效果:
由于设置了背景图,冷启动时会观察到从背景图切换到启动页图的效果。
iOS 上启动页的实现
iOS 实现原理与 Android 类似,通过添加一个 Launch Image 或者修改 LaunchScreen.xib 来控制启动屏的显示内容,然后等到 JS Bundle 加载完再显示主页面。
这里我同样通过添加启动页图片来实现,xCode 中选择 Images.xcassets,然后 + → App Icons & Launch Images → New iOS Launch Image,选中 LaunchImage 并在右侧的 Attribute Inspector 中选择你需要支持的屏幕。最后将准备好的启动页图片拖到对应的型号下就可以了。附上启动页图片大小参照:Static Launch Screen Images
添加完启动页图片后,还需要修改以我们新添加的图片作为启动页,在 xCode 中选择 General → App Icons and Launch Images → Launch Images Source → Use Asset Catalog,再选择我们新添加的 LaunchImage 就可以了。注意可能要将 app 卸载后重新安装后,修改的启动页图片才可能生效。
效果图如下:
可以看到 iOS 上有一点和 Android 不同,由于 iOS 没有冷启动机制,所以不会出现背景图切换的问题。
代码见:AppRouter