Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
expo-splash-screen
Advanced tools
Provides a module to allow keeping the native Splash Screen visible until you choose to hide it.
The expo-splash-screen package is used to control and customize the splash screen for Expo and React Native apps. It allows developers to show a splash screen while the app is loading, hide it once the app is ready, and customize its appearance.
Preventing Auto-Hide
This feature allows you to prevent the splash screen from auto-hiding. This is useful if you need to perform some asynchronous operations before the splash screen is hidden.
import * as SplashScreen from 'expo-splash-screen';
SplashScreen.preventAutoHideAsync();
Hiding the Splash Screen
This feature allows you to manually hide the splash screen once your app is ready. This is typically done after your app has finished loading all necessary resources.
import * as SplashScreen from 'expo-splash-screen';
async function hideSplashScreen() {
await SplashScreen.hideAsync();
}
Showing the Splash Screen
This feature allows you to manually show the splash screen. This can be useful if you need to display the splash screen again after it has been hidden.
import * as SplashScreen from 'expo-splash-screen';
async function showSplashScreen() {
await SplashScreen.showAsync();
}
The react-native-splash-screen package provides similar functionality to expo-splash-screen, allowing you to control the splash screen in a React Native app. It offers methods to show and hide the splash screen, but it requires more manual setup compared to expo-splash-screen.
The react-native-bootsplash package is another alternative for managing splash screens in React Native apps. It provides a more customizable and flexible approach compared to expo-splash-screen, with support for different splash screen images for different devices and orientations.
expo-splash-screen
allows you to customize your app's splash screen, which is the initial screen users see when the app is launched, before it has loaded. Splash screens (sometimes called launch screens) provide a user's first experience with your application.
expo-splash-screen
contains a built-in feature for taking care of properly displaying your splash screen image. You can use the following resize modes to obtain behavior as if you were using the React Native <Image>
component's resizeMode
style.
CONTAIN
resize modeScale the image uniformly (maintaining the image's aspect ratio) so that both dimensions the width and height of the image will be equal to or less than the corresponding dimension of the device's screen.
COVER
resize modeScale the image uniformly (maintaining the image's aspect ratio) so that both the width and height of the image will be equal to or larger than the corresponding dimension of the device's screen.
NATIVE
resize modeAndroid only.
By using this resize mode your app will will leverage Android's ability to present a static bitmap while the application is starting up. Android (unlike iOS) does not support stretching of the provided image during launch, so the application will present the given image centered on the screen at its original dimensions.
Android |
https://user-images.githubusercontent.com/379606/120575878-b3afe980-c3d6-11eb-80c1-72441c22e8be.mp4 |
Animation above presents one of our known issues
Selecting this resize mode requires some more work to be done in native configuration.
Please take a look at the res/drawable/splashscreen.xml
and res/drawable/splashscreen_background.png
sections.
expo-splash-screen
supports per-appearance splash screens that respond to system appearance changes on iOS 13+ and dark-mode changes on Android 10+.
expo-splash-screen
allows customization of the StatusBar according to the ReactNative StatusBar API.
import * as SplashScreen from 'expo-splash-screen';
The native splash screen that is controlled via this module autohides once the ReactNative-controlled view hierarchy is mounted. This means that when your app first render
s view component, the native splash screen will hide. This default behavior can be prevented by calling SplashScreen.preventAutoHideAsync()
and later on SplashScreen.hideAsync()
.
SplashScreen.preventAutoHideAsync()
This method makes the native splash screen stay visible until SplashScreen.hideAsync()
is called. This must be called before any ReactNative-controlled view hierarchy is rendered (either in the global scope of your main component, or when the component renders null
at the beginning - see Examples section).
Preventing default autohiding might come in handy if your application needs to prepare/download some resources and/or make some API calls before first rendering some actual view hierarchy.
A Promise
that resolves to true
when preventing autohiding succeeded and to false
if the native splash screen is already prevented from autohiding (for instance, if you've already called this method).
Promise
rejection most likely means that native splash screen cannot be prevented from autohiding (it's already hidden when this method was executed).
SplashScreen.hideAsync()
Hides the native splash screen. Only works if the native splash screen has been previously prevented from autohiding by calling SplashScreen.preventAutoHideAsync()
method.
A Promise
that resolves to true
once the splash screen becomes hidden and to false
if the splash screen is already hidden.
SplashScreen.preventAutoHideAsync()
in global scopeApp.tsx
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import * as SplashScreen from 'expo-splash-screen';
// Prevent native splash screen from autohiding before App component declaration
SplashScreen.preventAutoHideAsync()
.then((result) => console.log(`SplashScreen.preventAutoHideAsync() succeeded: ${result}`))
.catch(console.warn); // it's good to explicitly catch and inspect any error
export default class App extends React.Component {
componentDidMount() {
// Hides native splash screen after 2s
setTimeout(async () => {
await SplashScreen.hideAsync();
}, 2000);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>SplashScreen Demo! 👋</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#aabbcc',
},
text: {
color: 'white',
fontWeight: 'bold',
},
});
SplashScreen.preventAutoHideAsync()
in component that initially renders null
App.tsx
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import * as SplashScreen from 'expo-splash-screen';
export default class App extends React.Component {
state = {
appIsReady: false,
};
async componentDidMount() {
// Prevent native splash screen from autohiding
try {
await SplashScreen.preventAutoHideAsync();
} catch (e) {
console.warn(e);
}
this.prepareResources();
}
/**
* Method that serves to load resources and make API calls
*/
prepareResources = async () => {
await performAPICalls(...);
await downloadAssets(...);
this.setState({ appIsReady: true }, async () => {
await SplashScreen.hideAsync();
});
}
render() {
if (!this.state.appIsReady) {
return null;
}
return (
<View style={styles.container}>
<Text style={styles.text}>SplashScreen Demo! 👋</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#aabbcc',
},
text: {
color: 'white',
fontWeight: 'bold',
},
});
Refer to the SplashScreen section of the Expo documentation.
For bare React Native projects, you must ensure that you have installed and configured the expo
package before continuing.
npx expo install expo-splash-screen
Run npx pod-install
after installing the package.
To achieve native splash screen (in iOS ecosystem it's called LaunchScreen
) behavior, you have to provide either a SplashScreen.storyboard
file or a SplashScreen.xib
file, and configure your Xcode project accordingly.
The guide below shows how to configure your Xcode project to use a single image file as a splash screen using a .storyboard
file (configuration for .xib
filetype is analogous).
Images.xcassets
SplashScreen.storyboard
Content Mode
for the ImageView
in SplashScreen.storyboard
SplashScreen.storyboard
as the LaunchScreenImages.xcassets
First you need to add the image file that would serve as a splash screen to your native project's resources.
.xcassets
(often named Images.xcassets
or Assets.xcassets
) file.New image set
and name it SplashScreen
.SplashScreen.storyboard
This is the actual splash screen definition and will be used by the system to render your splash screen.
SplashScreen.storyboard
file.View Controller
to the newly created .storyboard
file:
Library
(+
button on the top-right),View Controller
element,.storyboard
file.Image View
to the View Controller
:
View
element from View Controller
,Library
(+
button on the top-right),Image View
element,View Controller
child in view hierarchy inspector.Storyboard ID
to SplashScreenViewController
:
View Controller
in view hierarchy inspector,Identity Inspector
in the right panel,Storyboard ID
to SplashScreenViewController
.Is Initial View Controller
in SplashScreenViewController
:
View Controller
in view hierarchy inspector,Attributes Inspector
in the right panel,Is Initial View Controller
in View Controller section.Image View
source:
Image View
in view hierarchy inspector,Attributes Inspector
in the right panel,SplashScreen
in Image
parameter).Background
of the Image View
:
Image View
in view hierarchy inspector,Attributes Inspector
in the right panel,Background
parameter:
#RRGGBB
value you need to select Custom
option and in the Colors Popup
that appeared you need to navigate to the second tab and choose RGB Sliders
from dropdown select.Content Mode
for the ImageView
in SplashScreen.storyboard
This is how your image will be displayed on the screen.
SplashScreen.storyboard
and select Image View
from View Controller
.Attributes Inspector
in the right panel and locate Content Mode
.Aspect Fit
to obtain CONTAIN resize mode,Aspect Fill
to obtain COVER resize mode.SplashScreen.storyboard
as the LaunchScreenThe newly created SplashScreen.storyboard
needs to be marked as the Launch Screen File
in your Xcode project in order to be presented from the very beginning of your application launch.
Project Navigator
TARGETS
panel and navigate to General
tab.App Icons and Launch Images
section and Launch Screen File
option.SplashScreen
as the value for located option.Depending on what iOS version your application is targeting, you have to adjust your native project differently to a obtain working per-appearance splash screen view.
You can take advantage of named colors
in your Xcode project.
Color Set
and customize its values for different color modes:
.xcassets
directory (either create a new .xcassets
for colors, or reuse an existing one e.g. with images) create New Color Set
and name it SplashScreenBackground
,Attributes Inspector
in the right panel and change Appearance
to Any, Dark
,Attributes Inspector
in the right panel for each mode.named color
as the Background
for the Image View
in SplashScreen.storyboard
:
SplashScreen.storyboard
and select Image View
in view hierarchy inspector,Attributes Inspector
in the right panel,Background
parameter by selecting your created named color
(that should be listed as SplashScreenBackground
).You cannot use named colors
feature in your Xcode project.
Instead you have to create an additional image set that contains small 1x1px images, each with the desired background color. Then, you'll use this additional image resource as a background in the splash screen view.
You can use this online generator to obtain 1x1px .png
images with desired colors: http://www.1x1px.me.
SplashScreenBackground
Image Set
with desired background colors for each mode in your Images.xcassets
directory:
.xcassets
directory with images,New image set
and name it SplashScreenBackground
,Image set
to support Dark Appearance
by navigating to Attributes Inspector
in the right panel and changing Appearance
to Any, Dark
,Update SplashScreen.storyboard
to consist of a single top-level View
with two Image View
subviews (solid-colored image in the background and actual splash screen image in the foreground):
SplashScreen.storyboard
and replace Image View
with a plain View
(search Library
for it and drag&drop it in place of current Image View
),Configure first Image View
(background color):
Attributes Inspector
:
Image
to SplashScreenBackground
(prepared in previous step),Content Mode
to Scale To Fill
(color needs to take all available space),Add new constraints
bottom menu,Constrain to margin
is not checked,View
(parent view reference) and set 0
as the value,0
value and parent view reference selected in dropdown) hit Add 4 Constraints
,View Hierarchy Inspector
constraints are added and Image View
resized to take whole place of parent view.Image View
(actual splash screen image):
Image View
and select correct Image
in Attributes Inspector
alongside with desired Content Mode
,You might want to add a separate image for dark
mode. If the system is switched to dark
mode, it would pick this different image instead of the normal one and present it in the splash screen view.
SplashScreen
(created in previous section).Dark Appearance
:Attributes Inspector
in the right panel,Appearances
section and select Any, Dark
,dark mode
by dropping it to the correct box.If you're targeting a version of iOS < 11 then you cannot use named color
feature and instead you need to generate images with desired background colors that are going to be used as the background for splash screen view.
There is this awesome 1x1px png online generator: http://www.1x1px.me (use it to generate two 1x1px images with desired background colors for different color modes).
You might want to customize the StatusBar appearance during the time the SplashScreen is being shown.
StatusBar hiding
flag:TARGETS
panel and navigate to Info
tab,Status bar initially hidden
attribute with desired value.StatusBar style
option:TARGETS
panel and navigate to Info
tab,Status bar style
attribute with desired value.To achieve fully-native splash screen behavior, expo-splash-screen
needs to be hooked into the native view hierarchy and consume some resources that have to be placed under /android/app/src/res
directory.
res/drawable/splashscreen_image.png
res/values/colors.xml
res/drawable/splashscreen.xml
res/values/styles.xml
AndroidManifest.xml
resizeMode
res/drawable/splashscreen_image.png
You have to provide your splash screen image and place it under the res/drawable
directory.
This image will be loaded as soon as Android mounts your application's native view hierarchy.
NATIVE
mode adjustmentsIf you've overridden <string name="expo_splash_screen_resize_mode">native</string>
mode in res/values/strings.xml
, you need to do a few additional steps.
In your application's res
directory you might want to have a number of drawable-X
sub-directories (where X
is the different DPI for different devices). They store different versions of images that are picked based on the device's DPI (for more information please see this official Android docs).
To achieve proper scaling of your splash screen image on every device you should have following directories:
res/drawable-mdpi
- scale 1x - resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.)res/drawable-hdpi
- scale 1.5x - resources for high-density (hdpi) screens (~240dpi).res/drawable-xhdpi
- scale 2x - resources for extra-high-density (xhdpi) screens (~320dpi).res/drawable-xxhdpi
- scale 3x - resources for extra-extra-high-density (xxhdpi) screens (~480dpi).res/drawable-xxxhdpi
- scale 4x - resources for extra-extra-extra-high-density (xxxhdpi) uses (~640dpi).Each of directories mentioned above should contain the same splashscreen_image.png
file, but with a different resolution (pay attention to scale factors).
res/values/colors.xml
This file contains colors that are reused across your application at the native level. Update the file with the following content or create one if missing:
<resources>
+ <color name="splashscreen_background">#AABBCC</color> <!-- #AARRGGBB or #RRGGBB format -->
<!-- Other colors defined for your application -->
</resources>
res/drawable/splashscreen.xml
This file contains the description of how the splash screen view should be drawn by the Android system. Create the file with the following content:
+ <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@color/splashscreen_background"/>
+ </layer-list>
NATIVE
mode adjustmentsIf you've overridden <string name="expo_splash_screen_resize_mode">native</string>
mode in res/values/strings.xml
, you shoulw add:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/splashscreen_background"/>
+ <item>
+ <bitmap android:gravity="center" android:src="@drawable/splashscreen_image"/>
+ </item>
</layer-list>
res/values/styles.xml
Locate your main activity theme in /android/app/src/res/values/styles.xml
or create one if missing.
<!-- Main activity theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
+ <item name="android:windowBackground">@drawable/splashscreen</item> <!-- this line instructs the system to use 'splashscreen.xml' as a background of the whole application -->
<!-- Other style properties -->
</style>
AndroidManifest.xml
Adjust your application's main AndroidManifest.xml
to contain an android:theme
property pointing to the style that contains your splash screen configuration:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
...
<application ...>
+ <!-- Ensure that 'android:theme' property is pointing to the style containing native splash screen reference - see 'styles.xml' -->
<activity
android:name=".MainActivity"
+ android:theme="@style/AppTheme"
...
>
...
</activity>
</application>
</manifest>
resizeMode
The default image resizeMode
is CONTAIN
. If you want to have different resizeMode
, you need to override in res/values/strings.xml
.
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resources>
<string name="app_name">sdk42</string>
+ <string name="expo_splash_screen_resize_mode">contain|cover|native</string>
</resources>
res/values-night/colors.png
If you want to have different background colors in your splash screen depending on the system color mode, you need to create a similar file to colors.xml
, but in the directory res/values-night
.
Values in this file are going to picked by the system when it is switched to dark
mode.
<resources>
+ <color name="splashscreen_background">#AABBCC</color> <!-- #AARRGGBB or #RRGGBB format -->
</resources>
res/drawable-night/splashscreen_image.png
You might want to provide a separate splash screen image for dark mode usage, and place it under the res/drawable-night
directory with exactly the same name as the normal one.
This step is optional, because you might want to have the same image in both light
and dark
modes (e.g. you have just a light-themed logo and you want to have different background colors in different modes).
You might want to customize the StatusBar appearance during the time the SplashScreen is being shown.
StatusBar hiding
flagTo have the StatusBar completely hidden you need to update your res/values/styles.xml
file with the following entry (to prevent StatusBar from hiding either remove this entry or enter false
as the value):
<!-- Main/SplashScreen activity theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splashscreen</item>
+ <item name="android:windowFullscreen">true</item>
<!-- Other style properties -->
</style>
If you have multiple styles.xml
files located in different directories containing exactly the same style
entry (e.g. in res/values-night
, res/values-night-v23
, etc.), be sure to update these files accordingly.
Read more about android:windowFullscreen
flag in official Android documentation.
StatusBar style
optionThis option is only available for Android devices running Android 6.0 or greater.
To enforce light
or dark
StatusBar style for given system color mode, you have to prepare or update your res/values-v23/styles.xml
file with the following entry (as of this option being supported since API 23, you have to configure specifically named directory containing separate configuration files):
<!-- Main/SplashScreen activity theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splashscreen</item>
+ <item name="android:windowLightStatusBar">true|false</item>
<!-- Other style properties -->
</style>
Available values:
true
for having dark-colored icons,false
for having light-colored icons.If you have multiple styles.xml
files located in different directories containing exactly the same style
entry (e.g. in res/values-night-v23
(for dark color mode), etc.), be sure to update these files accordingly.
Read more about android:windowLightStatusBar
flag in official Android documentation.
To read more about Android multi-API-level support see this official documentation.
StatusBar color
option (a.k.a. background color
of the StatusBar component)To achieve custom background color you need to create a new color resource and provide it to the SplashScreen style
description.
Create new color resource in your res/values/colors.xml
(if your application supports dark mode, consider adding different color in res/values-night/colors.xml
file):
<resources>
<color name="splashscreen_background">#D0D0C0</color>
+ <color name="splashscreen_statusbar_color">#(AA)RRGGBB</color> <!-- #AARRGGBB or #RRGGBB format -->
</resources>
Update your res/values/styles.xml
file with the following entry:
<!-- Main/SplashScreen activity theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splashscreen</item>
+ <item name="android:statusBarColor">@color/splashscreen_statusbar_color</item>
<!-- Other style properties -->
</style>
If you have multiple styles.xml
files located in different directories containing exactly the same style
entry (e.g. in res/values-night
, res/values-night-v23
, etc.), be sure to update these files accordingly.
Read more about android:statusBarColor
option in official Android documentation.
StatusBar translucent
flagWhen the StatusBar is translucent, the app will be able to draw under the StatusBar component area.
To make the StatusBar translucent update your res/values/strings.xml
file with the following content:
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resources>
<string name="app_name">sdk42</string>
+ <string name="expo_splash_screen_status_bar_translucent">true</string>
</resources>
Contributions are very welcome! Please refer to guidelines described in the contributing guide.
Splash Screens on iOS apps can sometimes encounter a caching issue where the previous image will flash before showing the new, intended image. When this occurs, we recommend you try power cycling your device and uninstalling and re-installing the application. However, the caching sometimes can persist for a day or two so be patient if the aforementioned steps were unable to resolve the issue.
NATIVE
mode pushes splash image up a little bitSee NATIVE
mode preview above.
We are aware of this issue and unfortunately haven't been able to provide a solution as of yet. This is on our immediate roadmap...
We try to keep changes backward compatible, the code for expo-splash-screen
will still work as it used to be. However, if you are going to migrate as new style API, here are the steps:
--- a/android/app/src/main/java/com/helloworld/MainActivity.java
+++ b/android/app/src/main/java/com/helloworld/MainActivity.java
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
-import host.exp.exponent.experience.splashscreen.legacy.singletons.SplashScreen;
-import host.exp.exponent.experience.splashscreen.legacy.SplashScreenImageResizeMode;
-
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// This is required for expo-splash-screen.
setTheme(R.style.AppTheme);
super.onCreate(null);
- // SplashScreen.show(...) has to be called after super.onCreate(...)
- SplashScreen.show(this, SplashScreenImageResizeMode.CONTAIN, ReactRootView.class, false);
}
resizeMode
and statusBarTranslucent
in stings.xml--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resources>
<string name="app_name">sdk42</string>
+ <string name="expo_splash_screen_resize_mode">contain</string>
+ <string name="expo_splash_screen_status_bar_translucent">false</string>
</resources>
This module is based on a solid work from (many thanks for that 👏):
FAQs
Provides a module to allow keeping the native Splash Screen visible until you choose to hide it.
We found that expo-splash-screen demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 28 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.