Время прочтения — 13 минут

React Native Splash Screen — поддержка разных тем

Содержание
Всем привет! На связи команда dev.family. В этой статье мы делимся кратким гайдом по установке Splash Screen в кросс-платформенное приложение, написанное на React Native, с поддержкой нескольких тем.
Splash screen — первый экран, который видят пользователи перед тем, как прогрузиться в основное приложение. Этот экран, пожалуй, лучший способ сделать название вашей аппки, да и в целом, ее всю более запоминающейся.
Но это не основная роль splash screen. Под ним, например, можно спрятать получение данных с API и прогрузку основного приложения. Мы так делаем, когда показываем лоадер на экране при загрузке тех же данных. Это позволяет улучшить UX и демонстрировать пользователю сразу готовое приложение. А как следствие — убрать лишний лоадер при первом открытии.
В этом кратком гайде мы разберем установку splash screen сразу для iOS и Android на фреймворке react-native с использованием библиотеки react-native-splash-screen.

Пошаговая инструкция

Подготовительные работы

Для начала нужно установить саму библиотеку в проект:

yarn add react-native-splash-screen
После этого в папке ios нужно запустить команду для установки подов:

cd ios && pod install && cd ..
(заходим в ios директорию, устанавливаем поды и возвращаемся обратно)
Далее есть два варианта настройки:
1
Использовать для splash screen картинку, экспортированную, например, из той же Figma
2
Сделать этот экран ручками, что сложнее и дольше.
Разберемся вначале с самим экраном.
Допустим, мы выбрали вариант, когда используется картинка. Экспортируем ее в высоком разрешении (в нашем случае х3). Но, так как мы сразу делаем все для двух тем, нужно экспортировать оба экземпляра (для светлой и темной). Далее переходим на AppIcon и перетаскиваем вначале одну картинку, затем другую.
Потом нажимаем Generate, скачиваем ассеты и помещаем в папку assets в корне проекта.
На этом общие приготовления завершены, перейдем непосредственно к установке в мобильное приложение. Начнем с iOS.

Настройка Splash Screen IOS

Первым делом открываем .xcworkspace нашего проекта. Там видим пустой AppIcon (если вы не добавляли иконку приложения или другие ассеты). Теперь создаем image set файл. Назовем его, например, SplashScreen (да очень оригинально, знаю :) ).
После создания в настройках мы видим Apperances с выбранным вариантом None. Нажимаем на него и выбираем Any, Light, Dark. В Any и Light перетаскиваем ассеты для светлой темы iOS. В Dark — для темной, соответственно. Получается вот так:
На этом почти все.
Открываем LaunchScreen.storyboard. Выбираем View Controller Scene > View Controller > View и удаляем оттуда все. После этого выбираем View, нажимаем на значок треугольника справа вверху и убираем галочку с Layout Guides > Safe Area. Нажимаем на плюс и добавляем в наш View Image View. Убираем все отступы и галочку с Constraints to margins.
В настройках справа указываем ресурс на наш Splash Screen. И выбираем Content View, который нам больше подходит. В данном случае — Scale To Fill. Но в большинстве подходит Aspect Fit.
Здесь же можно посмотреть темную тему и проверить, что картинка правильно изменилась.
C легкой частью установки на iOs мы разобрались.
Что касается сложной, все намного веселее. Готового решения я предоставить не могу. Придется самим экспортировать все картинки и цвета, из которых состоит ваш Splash Screen, и настраивать LaunchScreen.storyboard ручками.
Мы покажем, как это сделано у нас:
В общем, как видно со скриншотов, методика похожа, за исключением того, что добавляется не одна цельная картинка, а составной экран. Но делаем все подобным образом: добавляем цвета, к ним ставим разные палитры в зависимости от темы, а с картинками поступаем как в примере выше.
Наибольшую сложностью данного подхода является масштабирование под разные модели iPhone. Это решается разными отступами. Они могут быть статичными: применяются одинаково на всех моделях. Условно 30px слева, — и на всех моделях будет так, вне зависимости от того, меньше экран или больше. А могут быть и динамические отступы, как, например, в случае с лого. Все настраивается в настройках View (для изображения):
Как и расположение для экранов разных моделей. Наверное, даже будет правильнее сказать отступ, который сохраняется:
Одним словом, если выберите этот способ, придется поиграться самим.
Последний штрих — перейти в AppDelegate.m файл и добавить следующее:

[super application:application didFinishLaunchingWithOptions:launchOptions];


  [RNSplashScreen show]; // вызываем наш SplashScreen


  return YES;
Вместо строчки
 return [super application:application didFinishLaunchingWithOptions:launchOptions];
И добавить импорт

#import "RNSplashScreen.h"

Настройка Android

С iOS разобрались, теперь приступим к настройке Android. Тут тоже начнем с простого варианта, когда используем просто картинку.
Первым делом переносим сгенерированные материалы в папку res (android > app > src > main > res). Выходит вот так:
Дальше переходим в папку res > values и создаем файл theme.xml, вставляем туда следующее
    
<?xml version="1.0" encoding="utf-8"?>
    <resources>
      <attr name="launchImage" format="reference"/>
    </resources>
Здесь мы добавили кастомный атрибут launchImage.
Далее переходим в файл styles.xml (android/app/src/main/res/values/styles.xml) и добавляем следующее:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <resources>

      <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        ....
      </style>

      <!-- Добавляем это -->
      <style name="LightTheme" parent="AppTheme">
        <item name="launchImage">@drawable/launch_screen_light</item>
      </style>

      <!-- Добавляем это -->
      <style name="DarkTheme" parent="AppTheme">
        <item name="launchImage">@drawable/launch_screen_dark</item>
      </style>

    </resources>
Тут мы добавили две темы Light Theme и Dark Theme, и записали значения, которые предопределяют нашу картинку для launchImage.
После чего в нашей папке res создаем папку layout и в нее добавляем файл launch_screen.xml. В этот файл записываем:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView 
            android:layout_width="match_parent" 
            android:layout_height="match_parent"
            android:src="?attr/launchImage"
            android:scaleType="centerCrop" 
        />
    </RelativeLayout>
Здесь мы определяем ссылку на наш атрибут картинки. Обратите внимание на android:scaleType=”fitXY”. Вам может не подойти это значение, доступные варианты ищите тут.
Наконец переходим в MainActivity.java (android > app > src > main > java > com > packageName > appName > MainActivity.java) и перезаписываем метод onCreate на следующее:

@Override
protected void onCreate(Bundle savedInstanceState) {
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
case Configuration.UI_MODE_NIGHT_YES:
setTheme(R.style.DarkTheme);


break;
case Configuration.UI_MODE_NIGHT_NO:
setTheme(R.style.LightTheme);
break;
default:
setTheme(R.style.LightTheme);
}


SplashScreen.show(this);
super.onCreate(savedInstanceState);
}
В методе super.onCreate() передаем null, если используется пакет react-native-screens.
Также в самом верху нужно добавить два импорта

import org.devio.rn.splashscreen.SplashScreen;
import android.content.res.Configuration;


public class MainActivity extends ReactActivity { … 

Имплементация библиотеки

Вот и все приготовления завершены. Теперь осталось только имплементировать библиотеку в нашем приложении
App.tsx
// импортируем библиотеку

import SplashScreen from 'react-native-splash-screen' 

export default function App {

    useEffect() {
    // здесь может быть любой асинхронный код 
    // перед открытием приложения

    // прячем наш Splash Screen
        SplashScreen.hide();
    }

    . . . функция рендера

}
Остается сделать yarn run ios / yarn run android и убедиться, что все хорошо работает.
На этом все. Наш гайд по имплементации Splash Screen под разные темы на react-native закончен. Надеемся, он вам поможет, и помните, что Splash Screen — довольно важная часть приложения, так как это первое что видит пользователь. Так что не относитесь к нему с пренебрежением. Всего хорошего! На связи была команда dev.family, до скорых встреч!