Skip to content

Instantly share code, notes, and snippets.

@osiloke
Forked from RidaRidss/Add React Native Splash
Created March 22, 2019 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osiloke/0b960b693ce49bda042e0284a9853be4 to your computer and use it in GitHub Desktop.
Save osiloke/0b960b693ce49bda042e0284a9853be4 to your computer and use it in GitHub Desktop.
1. Make it look like the icon the user taps grows to fill the entire screen making for a seamless transition.
2. Keep it simple. A splash screen should only show for a few milliseconds. It shouldn’t have a lot of information on it — it is, after all, a dreaded loading screen.
3. With all of this in mind we’ll start with a a square image at three sizes (@1x = 200px, @2x = 400px, @3x = 600px).
Preparing the App
If you’ve tried to set up a splash screen in React Native then you may have experience a white screen flash before your content loads. If your app has a white background this is often not very noticable, but it’s still a pain. Today we’re going to make it very noticable if we have any flashes of white. To do that we’ll set a dark background color in our app.
Replace App.js with
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
StatusBar
} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<StatusBar
barStyle="light-content"
backgroundColor="#4F6D7A"
/>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#4F6D7A',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
color: '#F5FCFF',
},
instructions: {
textAlign: 'center',
color: '#F5FCFF',
marginBottom: 5,
},
});
All this did was set the background color to #4F6D7A, the text color to #F5FCFF, and use light text in the status bar.
Adding Splash Screens (iOS)
============================
First open the project in Xcode.
open ios/SplashExample.xcodeproj
We then want to add a new image asset inside of Xcode. You can access that in the left navigator — SplashExample > SplashExample > Imagex.xcassets and then pressing the “+” in the second left most navigator. Call it “SplashIcon”
https://cdn-images-1.medium.com/max/2000/1*hA4o97tl_aZiXCthovLbpg.png
Then go ahead and add the three images you downloaded earlier. They’ll automatically attach themselves to the right pixel density.
https://cdn-images-1.medium.com/max/2000/1*hUPU6q3U8be2uNiCuI0dBg.png
You can then open LaunchScreen.xib, again available in the left most navigator. You should see this.
https://cdn-images-1.medium.com/max/2000/1*P_xNvcvrGH0znF1vfXccPA.png
Select the two text elements (“SplashExample” and “Powered by React Native”) and delete them.
Next we’ll set the background color of the View. Select “View” in the second left most navigator. Then, in the right most navigator, choose “Background” which will pop up a picker dialog.
https://cdn-images-1.medium.com/max/2000/1*dW6KQzOAspmGOMD3EMJZew.png
https://cdn-images-1.medium.com/max/1600/1*r5NJ-ZNXAoe_ft5Pv88JkA.png
Go ahead and set the background color to #4F6D7A.
We then want to add an Image View to our splash screen. You can find that by pressing the third option in the bottom right menu and searching for “image”. When you’ve got that drag it onto the blue View.
https://cdn-images-1.medium.com/max/2000/1*OqUBamK88BHbeO-v2ZuBxA.png
You then want to set the image source from the top right. When you select the image dropdown any images from Images.xcassets should show up — choose SplashIcon.
https://cdn-images-1.medium.com/max/2000/1*0RPTYrrfyMEKjWMvtnUHhg.png
Now to fix proportions set the “Content Mode” to “Aspect Fit”. This is available in the right most menu, second down.
https://cdn-images-1.medium.com/max/2000/1*SmHSDhdsGfxD0Zkr9Wk_6w.png
Next, we need to make sure our icon stays centered in the screen regardless of what device the app is running on. To do this, in the right most navigator, choose the fifth icon at the top (the one that looks like a ruler).
https://cdn-images-1.medium.com/max/2000/1*mii0K718YMyqc0oYpk663w.png
Within the “Autoresizing” section you’ll want to disable the outter red lines and enable the inner red arrows. This will allow the image to stay centered regardless of the screen dimensions.
https://cdn-images-1.medium.com/max/1600/1*3j2jly6optvbprS-PT5cZQ.png
That leaves us with the following:
Now to handle that pesky white screen flash…
First, why does that happen? That’s when the Javascript is loading & the bridge is initializing. At least that’s the way I think about it. The splash screen displays when the app is first booted up (React Native). Then while React Native is initializing we get that white screen so what we need to do is “hold” the splash screen a bit longer than the default behavior.
That’s where we’ll use react-native-splash-screen.
First install the package and then link it.
yarn add react-native-splash-screen@3.0.6
react-native link react-native-splash-screen
We then need to configure the package. From Xcode open the AppDelegate.m file.
We’ll then add #import “SplashScreen.h" with the other imports and then add [SplashScreen show]; just above return YES; in the didFinishLaunchingWithOptions method.
https://cdn-images-1.medium.com/max/2000/1*KzQJDjcsVXpqKQC62X5_Xg.png
Finally, in App.js, we need to tell the splash screen to hide once our app is ready. We’ll do that in the componentDidMount lifecycle hook.
https://cdn-images-1.medium.com/max/1600/1*qVLxris9nFWtKgl-o1motQ.gif
Woo! Looking good. One last nitpick. Let’s set the statusbar color to light when the splash screen is shown. Open Info.plist in Xcode and add a new row to it. The key should be “UIStatusBarStyle” and the value (a string) to “UIStatusBarStyleLightContent”.
https://cdn-images-1.medium.com/max/2000/1*bMxDB4GOps4U_bv4CX8STw.png
And that leaves us with perfection
Adding Splash Screens (Android)
===============================
Android is a touch more complicated than iOS because we need to create two separate splash screens. One is used by react-native-splash-screen and the other is used before the app “inflates”. It’s also probably more difficult because I’m not as familiar with Android Studio. 😄
The first think we’ll do is add the image assets you previously downloaded to the mipmap directories in the android project. Android handles different pixel densities different than iOS so we’ll have to make some modifications.
First of all the mipmap folders exist in android/app/src/main/res and each pixel density has a different density appended to the directory name. Here’s where images should go
mipmap-mdpi = icon.png
mipmap-hdpi = icon@2x.png
mipmap-xhdpi = icon@3x.png
mipmap-xxhdpi = icon@3x.png
Once there rename the files so they’re icon.png instead.
https://cdn-images-1.medium.com/max/1600/1*IU3Jp1Hd9zqfbYAdrepNXg.png
Next we’ll go ahead and create the splash screen that is displayed when the app first launches from a cold start.
First create a background_splash.xml file in android/app/src/main/res/drawable (you’ll likely have to create the drawable directory).
Add the following code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/blue"/>
<item
android:width="200dp
android:height="200dp"
android:drawable="@mipmap/icon"
android:gravity="center" />
</layer-list>
https://cdn-images-1.medium.com/max/2000/1*8X71xlhfLwYfG3ruk-4Rlg.png
What we’re doing here is setting up a layer-list (a list of layers) then setting a background color (which we'll define shortly) and finally rendering our icon. The icon will be 200dp tall and wide and centered in the screen.
Next we’ll create a colors.xml in android/app/src/main/res/values in which we'll define our blue color (which is the same as the blue in our application).
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="blue">#4F6D7A</color>
</resources>
Then we create a new SplashTheme in the android/app/src/main/res/values/styles.xml file.
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/background_splash</item>
<item name="android:statusBarColor">@color/blue</item>
</style>
We’re telling it to use the background_splash we just defined as the window background and we're also telling it to use the blue color for the statusbar. I'm trying to emulate the actual app as much as possible here, thus the status bar change.
While we’re here let’s go ahead and ensure that the default StatusBar of our primary app theme defaults to the correct color as well. That leaves us with a styles.xml of:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:statusBarColor">@color/blue</item>
</style>
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/background_splash</item>
<item name="android:statusBarColor">@color/blue</item>
</style>
</resources>
Now we need to tell our app to use the SplashTheme initially. We'll do that in AndroidManifest.xml. Inside of <application></application> add
<activity
android:name=".SplashActivity"
android:theme="@style/SplashTheme"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
And modify the MainActivity to be the following. Pay special attention to the android:exported="true" I added.
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:exported="true"
/>
That leaves me with an AndroidManifest.xml that looks like
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.splashexample"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".SplashActivity"
android:theme="@style/SplashTheme"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:exported="true"
/>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Now we need to create a SplashActivity.java file.
https://cdn-images-1.medium.com/max/2000/1*X4cFcrIyanNeNzvhA1kIPw.png
The purpose of this SplashActivity.java is to forward along to our MainActivity (the React Native app). It should look like this
package com.splashexample; // make sure this is your package name
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
Now, assuming everything is set up correctly, if you run the app then quit it (so it has to do a cold start) you should see the following.
Looking pretty good! We get the launch screen right away but then we get that white flash again…
Fixing it isn’t quite as easy on iOS, but still not too difficult.
If you haven’t already, install react-native-splash-screen and link it.
yarn add react-native-splash-screen@3.0.6
react-native link
We then need to configure the native android side.
In MainActivity.java add
package com.splashexample; // this should be your package name
import com.facebook.react.ReactActivity;
import org.devio.rn.splashscreen.SplashScreen; // import this
import android.os.Bundle; // import this
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this); // here
super.onCreate(savedInstanceState);
}
...
}
Then configure App.js in your application, if you haven’t already, to close the splash screen as soon as the app loads.
import SplashScreen from 'react-native-splash-screen';
export default class App extends Component {
componentDidMount() {
SplashScreen.hide()
}
...
}
Then you’ll want to create a launch_screen.xml (name matters!) inside of android/app/src/main/res/layout with a root element of LinearLayout.
https://cdn-images-1.medium.com/max/2000/1*YMSro5ezmn0BjwhcgFSxIw.png
https://cdn-images-1.medium.com/max/2000/1*sbwMXL3adK-woT5Pf4inUQ.png
Android Studio has an interface very similar to Xcode’s interface builder, but I’m not sure how it works so I’m just going to modify the elements directly.
First I’m going to set the gravity of the LinearLayout to center and the background color to blue. The rest is default setup.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/blue"
android:gravity="center">
</LinearLayout>
I’m then going to render an ImageView to render the icon inside of the LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/blue"
android:gravity="center">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="24dp"
android:src="@mipmap/icon"
/>
</LinearLayout>
About the properties on the ImageView.
android:layout_width, android:layout_height - set height and width. We want it to be the same as what we set in background_splash.xml.
android:layout_marginTop - this is the height of the status bar. If we omit this then the icons won't quite be in the same spot and you'll see a "jump" when the splash screens switch
android:src="@mipmap/icon" image to be rendered
Finally, inside of the colors.xml file we need to add:
<color name="primary_dark">#4F6D7A</color>
Otherwise the app will crash. This is a bug in react-native-splash-screen and may be fixed in a future release.
https://cdn-images-1.medium.com/max/1600/1*tfH-JhMPyMZrJmDAPviQ0w.gif
I hope you found this helpful!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment