Не занимаясь никогда ранее нативной разработкой под мобильные платформы, и в этот раз решил пойти "легким путем" — освоить React Native. Наибольшей трудностью стало добавление иконки приложения(AppIcon) и экрана загрузки (Launch Screen). О чем и хочу рассказать в данной статье тем, кто осваивает React Native.
На момент написания статьи актуальная версия React Native 41.0, XCode 8.2 (эти данные указаны по той причине, что в более поздних версиях может что-то измениться и данный мануал не будет применим).
Начнем...
Создаем React Native приложение
react-native init habr
Добавление AppIcon
На iOS
Идем в папку с iOS-частью приложения
cd habr/ios/
и открываем там файл XCode-проекта habr.xcodeproj.
Далее, щелкаем по следующим кнопкам:
В поле 4 добавляем иконки путем перетаскивания их в пустые ячейки. Под ячейками указан размер иконки(в pt).
Получается примерно так:
Важно: картинка иконки должна быть квадратная и, в идеале, их должно быть несколько версий разного размера(под каждую ячейку — свой размер). Если не охота возиться с созданием иконок разного размера — добавьте одну, размером 120x120px, в ячейку для iPhone 7-10:
Если добавить иконки не правильного размера, то получите ошибку "Images.xcassets: The app icon set named “AppIcon” did not have any applicable content."
Полезно знать: иконки для ios удобнее всего создавать в программе Sketch(доступна только под OS X), поскольку в ней есть шаблоны нужных размеров, которые затем можно экспортировать в png-формат (File > Export...):
Запускаем сборку ios-версии из корневой папки проекта:
react-native run-ios
Получаем профит:
(hit: для "сворачивания" приложения в эмуляторе нужно дважды нажать Cmd+Shift+H)
На Android
Из папки проекта идем в папку с Android-частью приложения, в место хранения ресурсов:
cd habr/android/app/src/main/res/
и видим здесь папки:
Заходим в каждую из них и в каждой видим файл ic_launcher.png. Заменяем каждый файл на свой, с таким же именем и такого же размера (в px).
Запускаем сборку Android-версии из корневой папки проекта:
react-native run-android
Получаем профит:
С иконками закончили, переходим к экрану загрузки.
Добавление LaunchScreen
На iOS
Существует по крайней мере 2 способа добавить LaunchScreen на iOS. Опишу тот, который сработал у меня.
Первым делом, идем снова в XCode, по тому же маршруту, который показан на самом первом изображении в этой статье, но вместо папки Images.xcassets, выбираем файл LaunchScreen.xib.
При этом XCode спросит, для какой версии какого устройства отобразить содержимое данного файла. Выбираем любой iPhone.
Далее, щелкаем по кнопкам под номером 3 и 4 на данном скриншоте:
Затем перетаскиваем элемент 5 (Image View) на рабочее поле 6. Имеющиеся в рабочем поле 6 элементы (текстовые надписи) можно удалить.
Следующим шагом добавляем в наш проект нужное нам файл с изображением(для начинающих маководов — контекстное меню вызывается прикосновением к тачпаду двумя пальцами одновременно).
Далее, щелкаем по элементу UIImageView в рабочей зоне и настраиваем его свойства:
В меню под номером 1 (на скриншоте) выбираем добавленную в предыдущем шаге картинку(если выпадающий список пуст, то щелкните в левой панели(там где выбирали файл LaunchScreen.xib по любому другому файлу, а затем снова вернитесь к файлу LaunchScreen.xib — файл появится в выпадающем списке. Это мелкий баг XCode).
В меню под номером 2 выберите "Aspect Fit", чтобы картинка масштабировалась пропорционально, независимо от размера экрана устройства, на котором будет запущено приложение.
Чтобы картинка располагалась строго по центру, щелкните самой картинке(на рабочей области) и нажмите на кнопку 1, как показано на следующем скриншоте:
В каждом из четырех полей "Add new constrains" установите значение 0.
Запускаем сборку ios-версии из корневой папки проекта:
react-native run-ios
Получаем профит:
На Android
Из папки проекта идем в папку с Android-частью приложения, в место хранения ресурсов:
cd habr/android/app/src/main/res/
Добавляем здесь папку drawable. Создаем в ней файл splash_screen.xml такого содержания
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/white"/>
</item>
<item>
<bitmap
android:gravity="center"
android:src="@drawable/ic_launcher"/>
</item>
</layer-list>
Этот файл описывает новый "ресурс" приложения, и путь к внешним файлам ресурса(в нашем случае — к файлу с изображением для стартового экрана).
android:gravity="center"
эта часть кода указывает расположение ресурса на экране. А эта:
android:src="@drawable/ic_launcher"/>
путь к файлу ресурса, относительно папки res.
Блок кода
<item>
<color android:color="@color/white"/>
</item>
Создает фоновую подложку к экрану загрузки, а строка
@color/white
указывает цвет фона. Значение цвета фона берется из файла colors.xml, который пока не существует и который вам нужно создать и расположить по адресу:
*
habr/android/app/src/main/res/values/colors.xml
Содержимое файла может быть таким:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="orange">#ff5500</color>
<color name="white">#ffffff</color>
<color name="transparent">#00000000</color>
</resources>
Здесь каждая строчка вроде
<color name="white">#ffffff</color>
содержит цветовую константу. Задать цветовое значение фона напрямую(в файле splash_screen.xml) мне не удалось, поэтому добавил такой файл, как советовалось в одной из инструкций в Сети.
Далее, в папку drawable добавляем файл ic_launcher.png, представляющий собой изображение на стартовом экране.
Затем идем в папку
cd habr/android/app/src/main/res/values
и редактируем файл styles.xml так, чтобы он выглядел следующим образом
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
<!-- здесь мы добавляем свою часть кода -->
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowBackground">@drawable/splash_screen</item>
</style>
</resources>
Этим действием мы добавляем новую "тему оформления" для "активности"(activity).
"Активность"(Activity) в Android-приложениях представляет собой "экран" или "страницу". По умолчанию в React Native есть лишь одна "активность", мы же добавляем ещё одну.
Для этого переходим в папку с java-кодом:
cd habr/android/app/src/main/java/com/habr
(путь после /java/ в вашем проекте будет другим) и делаем следующее:
- переименовываем MainActivity.java в MainActivity2.java
- редактируем файл MainActivity2.java — меняем название класса в 6 строке с "MainActivity" на "MainActivity2":
public class MainActivity2 extends ReactActivity {
Создаем файл MainActivity.java, в который пишем такой код:
package com.habr;//здесь вы указываете название вашего пакета import android.content.Intent; import android.os.Bundle; import com.facebook.react.ReactActivity; public class MainActivity extends ReactActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = new Intent(this, MainActivity2.class); startActivity(intent); finish(); } }
Смысл перечисленных выше 3-х шагов прост: мы меняем стартовый загрузочный экран("активность") на наш экран("активность) SplashScreen.
(В этом абзаце вы могли заметить, что LaunchScreen переименовался в SplashScreen. В Android-разработке(и не только) принято называть загрузочный экран SplashScreen'ом.)
Теперь осталось зарегистрировать нашу "активность" в файле-манифесте Android-приложения, чтобы она была доступна для вызова в коде.
Открываем файл AndroidManifest.xml, который находится по адресу
/android/app/src/main/AndroidManifest.xml
(относительно корневой директории проекта)
И приводим его к такому виду:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.habr"
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=".MainActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- эта "активность" - основной экран приложения -->
<activity
android:name=".MainActivity2"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
В итоге, в файле AndroidManifest.xml мы имеем 2 активности, причем в одной из них указано, что именно она — та, с которой начнется запуск Android-приложения. Это делается добавлением таких параметров:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
в тело "активности".
С приготовлениями закончено. Запускаем билд android-версии из корневой папки проекта:
react-native run-android
Получаем профит:
Полный код проекта можно найти здесь.
Комментарии (13)
zagayevskiy
27.02.2017 14:45Отвратительно. Да, самый нормальный способ сделать сплэш на андроиде — через бэкграунд в теме. Но. Зачем тут вторая активити? Это принесет вам баги. Просто надо занулять этот бэкграунд (getWindow().setBackgroundDrawable(null);) в onCreate activity, чтобы не было overdraw (лишнего слоя отрисовки).
Про иконки вообще не понял. Кто-то может этого не знать? о_О Пусть прочтёт документацию.frog
27.02.2017 15:21-1Человек пишет, как сделать это в рамках React Native. А вы предлагаете написать код на Java?
zagayevskiy
28.02.2017 15:00Вы бы хоть код его почитали. Он как раз писал код на джаве. При этом он написал куда больше кода, чем предлагаю я. Лишнего и вредного кода.
redflasher
27.02.2017 20:28Как бы вы написали код для сплэша в андроиде?(если можно — пришлите рабочий пример, я внесу правки в статью)
Важный нюанс — разработчики на React Native совсем не обязательно знакомы с нативной разработкой под Android и iOS.
То есть, хотелось бы, в идеале, copy&paste-решение(поскольку не всем понравится мысль что надо изучать Android Development ради того, чтобы более правильно добавлять сплеш-скрин).zagayevskiy
28.02.2017 15:03Я же сказал, как надо сделать. В теме вы правильно всё сделали, но для сплэша не нужна вторая отдельная активити. Надо ставить бэкграунд в тему активити-лаунчера и занулять его в onCreate.
redflasher
01.03.2017 00:07Да, я видел ваш код. Просто сам на Java последний раз лет 10 назад кодил(J2ME еще). Боюсь допустить неточность, самостоятельно внося правки в код статьи.
Подумал, что вы захотите прислать свое видение кода MainActivity.java.
А так да, наверняка еще вернусь к этому вопросу, и тогда разберусь с этим. Спасибо за подсказку!zagayevskiy
01.03.2017 08:09А чей же тогда код на джаве в статье?
redflasher
01.03.2017 14:46stackoverflow
zagayevskiy
01.03.2017 15:35То есть вы скопипастили код, не разобрались в нём и ещё сляпали статью на хабр? Не зря я вам минус в карму влепил.
drakmail
Для иконок есть еще сервис makeappicon.com, через который можно сразу сделать иконки всех размеров