How to Configure App Icons and Splash Screens in React Native
App icons and splash screens are essential for branding and user experience in React Native applications. The app icon represents your app on a user’s device, while the splash screen ensures a polished loading experience during startup. This guide provides a step-by-step process to configure app icons and splash screens for iOS and Android using Expo SDK 51 and [email protected]
, compatible with React Native 0.75.4 (July 2025). It assumes basic knowledge of JavaScript and React Native, with no prior native configuration experience required.
For prebuilt solutions, explore templates at Instamobile or Dopebase.
By the end, you’ll have a React Native app with a custom app icon and splash screen, optimized for development, staging, and production environments on both platforms.
Prerequisites
Before starting, ensure you have the following installed:
- Node.js (v20.x or later, LTS recommended): Download from nodejs.org.
- npm (v10.x or later, included with Node.js).
- Expo CLI: For streamlined React Native project setup.
- Android Studio (2024.3.2 or later): For Android development, with Android SDK 35 and NDK r25+.
- Xcode (16+): For iOS development (macOS only). iOS builds require Xcode 16+ (iOS 18 SDK) to comply with App Store submission requirements after April 24, 2025.
- A code editor like VS Code.
- Git: For cloning repositories or managing code.
- A 1024x1024 PNG image for the app icon and a 2000x2000 PNG image for the splash screen (transparent background recommended).
Step 1: Set Up the React Native Project
-
Install Expo CLI globally to simplify React Native development:
npm install -g expo-cli
-
Create a new project called
MyApp
:expo init MyApp
Select the blank (TypeScript) template for a type-safe setup. Expo SDK 51 supports React Native 0.75.4 (July 2025) with the New Architecture enabled.
-
Navigate to the project directory:
cd MyApp
-
Install
react-native-bootsplash
for splash screen management:npm install [email protected]
-
Update
app.json
to exclude incompatible dependencies:{
"expo": {
"install": {
"exclude": ["react-native-reanimated@~3.10.0"]
}
}
}
Summary: This step sets up a new React Native project with Expo SDK 51 and installs react-native-bootsplash
for splash screen configuration.
Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount 🔥
Get the Mega BundleStep 2: Configure the App Icon
App icons must be 1024x1024 PNG images without rounded corners or transparency, as the operating system applies masking. Expo CLI and EAS Build simplify icon generation, but manual steps are provided for bare workflows.
iOS Configuration
- Create a 1024x1024 PNG icon using tools like App Icon Generator. Save it as
icon.png
inassets/images
. Optionally, create dark mode variants (icon-dark.png
). - Update
app.json
to specify the icon:EAS Build generates all required icon sizes (e.g., 180x180, 120x120).{
"expo": {
"icon": ".https://docs.instamobile.io/assets/images/icon.png",
"ios": {
"icon": {
"any": ".https://docs.instamobile.io/assets/images/icon.png",
"dark": ".https://docs.instamobile.io/assets/images/icon-dark.png"
}
}
}
} - For bare workflows, open
ios/MyApp.xcworkspace
in Xcode, navigate toImages.xcassets
>AppIcon
, and dragicon.png
into the appropriate slots.
Android Configuration
- Use the same 1024x1024 PNG icon, optionally creating adaptive icon layers (foreground and background) in Android Studio’s Image Asset Studio.
- Update
app.json
:EAS Build generates all required sizes (e.g.,{
"expo": {
"icon": ".https://docs.instamobile.io/assets/images/icon.png",
"android": {
"adaptiveIcon": {
"foregroundImage": ".https://docs.instamobile.io/assets/images/icon-foreground.png",
"backgroundColor": "#ffffff"
}
}
}
}mipmap-mdpi
,mipmap-xhdpi
). - For bare workflows, copy icons to
android/app/src/main/res/mipmap-*
folders and updateandroid/app/src/main/AndroidManifest.xml
:<application
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round">
Summary: App icons are configured in app.json
for Expo-managed projects or manually in Xcode and Android resource folders for bare workflows, ensuring platform-specific compatibility.
Step 3: Configure the Splash Screen
Splash screens display during app startup and should feature a centered logo on a solid background for fast loading. The react-native-bootsplash
library provides robust control for both platforms.
Prepare the Splash Screen Image
Create a 2000x2000 PNG image with a transparent background, ensuring no critical elements are near the edges to account for safe areas. Save it as splash-icon.png
in assets/images
. Use tools like Figma for design consistency.
iOS Configuration
- Generate splash screen assets:
This creates
npx react-native generate-bootsplash assets/images/splash-icon.png \
--platforms=ios \
--background=#ffffff \
--logo-width=200BootSplash.storyboard
and assets inios/MyApp/Images.xcassets
. - Update
app.json
:{
"expo": {
"splash": {
"image": ".https://docs.instamobile.io/assets/images/splash-icon.png",
"backgroundColor": "#ffffff",
"resizeMode": "contain",
"dark": {
"image": ".https://docs.instamobile.io/assets/images/splash-icon-dark.png",
"backgroundColor": "#000000"
}
}
}
} - For bare workflows, open
BootSplash.storyboard
in Xcode, add anImageView
withsplash-icon
fromImages.xcassets
, setContent Mode
toAspect Fit
, and center it using constraints. UpdateInfo.plist
to setUILaunchStoryboardName
toBootSplash
. - Update
ios/MyApp/AppDelegate.mm
to initialize the splash screen:#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNSplashScreen.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"MyApp" initialProperties:nil];
rootView.backgroundColor = [UIColor whiteColor];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[RNSplashScreen show];
return YES;
}
@end
Android Configuration
- Generate splash screen assets:
This generates assets in
npx react-native generate-bootsplash assets/images/splash-icon.png \
--platforms=android \
--background=#ffffff \
--logo-width=200android/app/src/main/res/drawable
and aBootSplash
theme. - Update
android/app/src/main/res/layout/launch_screen.xml
:<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/bootsplash_logo"
android:scaleType="centerCrop" />
</RelativeLayout> - Update
android/app/src/main/AndroidManifest.xml
:<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".SplashActivity"
android:theme="@style/BootTheme"
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" />
</application>
</manifest> - Update
android/app/src/main/java/com/myapp/MainActivity.java
:package com.myapp;
import com.facebook.react.ReactActivity;
import android.os.Bundle;
import com.zoontek.rnbootsplash.RNBootSplash;
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
RNBootSplash.init(this, R.style.BootTheme);
super.onCreate(savedInstanceState);
}
}
Hide Splash Screen
Update src/App.tsx
to hide the splash screen after loading:
import { useEffect } from 'react';
import { View, Text } from 'react-native';
import SplashScreen from 'react-native-bootsplash';
export default function App() {
useEffect(() => {
const init = async () => {
await new Promise(resolve => setTimeout(resolve, 2000)); // Simulate loading
await SplashScreen.hide({ fade: true });
};
init();
}, []);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Welcome to MyApp!</Text>
</View>
);
}
Summary: Splash screens are configured using react-native-bootsplash
and app.json
for Expo, or manually with storyboards and layouts for bare workflows, ensuring a smooth startup experience.
Step 4: Configure Staging and Production Environments
To distinguish staging and production builds, use unique icons and splash screens for each environment.
-
Update
app.config.ts
for dynamic configuration:import { ConfigContext, ExpoConfig } from 'expo/config';
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: process.env.APP_ENV === 'staging' ? 'MyApp Staging' : 'MyApp',
icon: process.env.APP_ENV === 'staging' ? '.https://docs.instamobile.io/assets/images/icon-staging.png' : '.https://docs.instamobile.io/assets/images/icon.png',
splash: {
image: process.env.APP_ENV === 'staging' ? '.https://docs.instamobile.io/assets/images/splash-icon-staging.png' : '.https://docs.instamobile.io/assets/images/splash-icon.png',
backgroundColor: '#ffffff',
resizeMode: 'contain',
},
}); -
iOS Configuration:
- In Xcode, duplicate the app target (
MyApp
→MyApp-Staging
). - Create separate
Images.xcassets
folders for each target (e.g.,Images-Staging.xcassets
). - Add unique icons and splash images for each environment.
- Update
Info.plist
for each target to reference the correctBootSplash
storyboard.
- In Xcode, duplicate the app target (
-
Android Configuration:
- In
android/app/build.gradle
, define product flavors:android {
flavorDimensions "default"
productFlavors {
staging {
dimension "default"
applicationIdSuffix ".staging"
resValue "string", "app_name", "MyApp Staging"
}
production {
dimension "default"
resValue "string", "app_name", "MyApp"
}
}
} - Create separate resource folders (e.g.,
android/app/src/staging/res/drawable
,android/app/src/production/res/drawable
) with unique icons and splash images.
- In
Summary: Environment-specific icons and splash screens are configured using app.config.ts
for Expo or separate targets/flavors for bare workflows, enabling clear differentiation between staging and production.
Step 5: Build and Test
-
Generate native projects:
npx expo prebuild
-
Build for iOS:
npx expo run:ios
-
Build for Android:
npx expo run:android
Use preview or production builds to test splash screens, as Expo Go may override custom configurations.
-
Test staging vs. production:
- For iOS, select the
MyApp-Staging
target in Xcode. - For Android, run
gradlew assembleStagingDebug
orassembleProductionRelease
. - Verify that the correct icons and splash screens appear for each environment.
- For iOS, select the
Summary: Build and test the app to ensure icons and splash screens display correctly across platforms and environments, using EAS Build for Expo or native tools for bare workflows.
Step 6: Enhance and Optimize
- Use
expo-dynamic-app-icon
to change icons programmatically for testing or branding. - Integrate
expo-custom-assets
for animated splash screens, as detailed in Expo’s 2025 documentation. - Optimize splash screen duration by preloading assets (e.g., fonts, APIs) in
App.tsx
. - Ensure icons are simple and splash screens are minimal to avoid visual clutter. Test on multiple devices for proper scaling.
Summary: Enhance the app with dynamic icons, animations, and optimized loading to improve user experience and maintainability.
Troubleshooting Tips
- iOS Caching Issues: Clear derived data (
rm -rf ~/Library/Developer/Xcode/DerivedData
) if icons or splash screens don’t update. - Android Scaling Issues: Use
centerCrop
orcenterInside
inlaunch_screen.xml
to prevent distortion across devices. - Library Linking: Run
npx pod-install
for iOS or sync Gradle for Android ifreact-native-bootsplash
fails. - Expo Build Issues: Ensure
app.json
orapp.config.ts
is correctly formatted and EAS Build is configured.
Looking for a custom mobile application?
Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.
Get in TouchConclusion
You’ve configured app icons and splash screens for a React Native app using Expo SDK 51 and [email protected]
, ensuring compatibility with React Native 0.75.4 (July 2025). The setup supports iOS 18 SDK (Xcode 16+) and Android SDK 35, with distinct configurations for staging and production environments. For faster development, explore prebuilt templates at Instamobile or Dopebase, which include production-ready icon and splash screen setups. Refer to Expo’s documentation and react-native-bootsplash for advanced features like animations.
Additional Resources
- dopebase.com - Mobile app development resources and templates
- instamobile.io - Production-ready React Native templates
- instaflutter.com - Flutter templates for cross-platform development
- reactnative.dev - Official React Native documentation
- appicon.co - Tool for generating app icons and splash screens