افزودن صفحه آغازین (Splash Screen) به اپ React Native — از صفر تا صد
مراحل نهاییسازی یک اپلیکیشن و ارائه آن در اپاستورهای مختلف به مراتب پیچیدهتر از توسعه خود آن است و شامل کارهایی مانند افزودن آیکونها، «صفحههای آغازین» (Splash Screens)، نوشتن توضیح و موارد دیگر میشود. در این مقاله به بررسی روش افزودن صفحه آغازین به اپهای ریاکت نیتیو برای پلتفرمهای iOS و Android میپردازیم.
بدین منظور روی IDE-های متناظر هر پلتفرم کار میکنیم و مقداری کد نیتیو مینویسیم. به هیچ وجه جای نگرانی وجود ندارد، زیرا توضیحات کاملاً جامع هستند. برای مشاهده کد نهایی میتوانید به این ریپوی گیتهاب (+) مراجعه کنید.
در ابتدا یک اپلیکیشن React Native جدید با دستور زیر میسازیم:
react-native init SplashExample
نکته: پیش از ادامه مطالعه این مقاله، کنترل سورس را راهاندازی کنید. این نهتنها یک روش مناسب برای بازگردانی تغییرات در صورت بروز اشتباه است، بلکه یک روش مناسب برای بررسی این نکته است که چه چیزی دقیقاً عوض شده است تا صفحه آغازین فعال شود.
فایلهای صفحه آغازین
ما در راهنما میتوانستیم از یک تصویر بزرگ برای صفحه آغازین استفاده کنیم، اما این امر موجب استفاده از مقیاسبندی بین وضوحهای مختلف صفحههای گوشی میشد که مداوماً نیز در حال رشد هستند. بنابراین به جای آن، کار خود را با یک تصویر منفرد آغاز میکنیم که بیشتر شبیه به آیکون به نظر میرسد. این ایده دو جنبه دارد:
وقتی تصویر شبیه آیکون است کاربر تشویق میشود که روی آن ضربه بزند و با این کار تصویر به اندازه صفحه بزرگ میشود و این کار در طی یک گذار بی توقف صورت میگیرد.
همه چیز ساده میماند. یک صفحه آغازین صرفاً برای چند میلیثانیه نمایش مییابد و نباید اطلاعات زیادی روی آن قرار داشته باشند چون در هر صورت یک صفحه بارگذاری محسوب میشود.
با داشتن این ذهنیت کار خود را با یک تصویر مربعی در سه اندازه زیر شروع میکنیم:
- @1x = 200px
- @2x = 400px
- @3x = 600px
این تصاویر را میتوانید از اینجا (+) دانلود کنید.
آمادهسازی اپلیکیشن
اگر تاکنون تلاش کرده باشید یک صفحه آغازین در React Native تنظیم کنید، ممکن است یک صفحه سفید را که پیش از بارگذاری محتوا چشمک میزند، تجربه کرده باشید. اگر اپلیکیشن شما دارای پسزمینه سفید باشد، این مسئله معمولاً چندان به چشم نمیآید، اما در هر صورت یک مشکل محسوب میشود.
در این راهنما قصد داریم کاری کنیم که اگر چنین چیزی وجود دارد، کاملاً به چشم بیاید. به این منظور یک رنگ پسزمینه تیره برای اپلیکیشن خود انتخاب میکنیم. به این منظور محتوای App.js را با کد زیر عوض کنید:
1import React, { Component } from 'react';
2import {
3 Platform,
4 StyleSheet,
5 Text,
6 View,
7 StatusBar
8} from 'react-native';
9
10const instructions = Platform.select({
11 ios: 'Press Cmd+R to reload,\n' +
12 'Cmd+D or shake for dev menu',
13 android: 'Double tap R on your keyboard to reload,\n' +
14 'Shake or press menu button for dev menu',
15});
16
17export default class App extends Component {
18 render() {
19 return (
20 <View style={styles.container}>
21 <StatusBar
22 barStyle="light-content"
23 backgroundColor="#4F6D7A"
24 />
25 <Text style={styles.welcome}>
26 Welcome to React Native!
27 </Text>
28 <Text style={styles.instructions}>
29 To get started, edit App.js
30 </Text>
31 <Text style={styles.instructions}>
32 {instructions}
33 </Text>
34 </View>
35 );
36 }
37}
38
39const styles = StyleSheet.create({
40 container: {
41 flex: 1,
42 justifyContent: 'center',
43 alignItems: 'center',
44 backgroundColor: '#4F6D7A',
45 },
46 welcome: {
47 fontSize: 20,
48 textAlign: 'center',
49 margin: 10,
50 color: '#F5FCFF',
51 },
52 instructions: {
53 textAlign: 'center',
54 color: '#F5FCFF',
55 marginBottom: 5,
56 },
57});
همه این کارها موجب شد که رنگ پسزمینه به #4F6D7A و رنگ متن به #F5FCFF عوض شود و از متن روشن در نوار وضعیت استفاده شود.
افزودن صفحه آغازین به iOS
ابتدا پروژه را در Xcode باز کنید.
1open ios/SplashExample.xcodeproj
سپس یک فایل تصویر جدید درون Xcode اضافه کنید. در ناوبری سمت چپ میتوانید به این فایل دسترسی پیدا کنید (SplashExample > SplashExample > Imagex.xcassets) و سپس کلید + را در ناوبری دوم سمت چپ کلیک کنید. نام آن را SplashIcon بگذارید.
سپس ادامه میدهیم و سه تصویر که قبلاً دانلود کردیم را به پروژه اضافه میکنیم. این تصاویر به صورت خودکار خودشان را به تراکم پیکسلی صحیح الحاق میکنند.
سپس میتوانید LaunchScreen.xib را که در ناوبری سمت چپ موجود است را باز کنید. بدین ترتیب با تصویر زیر مواجه میشوید.
دو عنصر متنی را انتخاب و آنها را حذف کنید.
سپس رنگ پسزمینه View را تنظیم میکنیم. به این منظور View را در ناوبری دوم سمت چپ انتخاب کنید و سپس در ناوبری سمت راست گزینه Background را انتخاب کنید که یک کادر محاورهای انتخاب رنگ را باز میکند.
نکته: اگر گزینه دوم را در کادر انتخاب رنگ انتخاب کرده و سپس RGB Sliders را کلیک کنید، میتوانید مقادیر عددی هگزادسیمال نیز وارد کنید.
در ادامه رنگ پسزمینه را به صورت #4F6D7A تعیین کنید.
سپس باید یک Image View به صفحه آغازین خود اضافه کنیم. این مورد را میتوانید با فشردن گزینه سوم منوی پایین-راست و جستجو به دنبال image بیابید. زمانی که یافتید، آن را روی View آبیرنگ بکشید.
سپس منبع تصویر را از سمت راست-بالا انتخاب کنید. زمانی که تصویر را انتخاب میکنید، همه تصاویر منوی بازشدنی Images.xcassets را نمایش دهید و گزینه SplashIcon را انتخاب کنید.
اکنون برای اصلاح نسبتها، Content Mode را روی Aspect Fit قرار دهید. این گزینه در منوی سمت راست و در جایگاه دوم از پایین قرار دارد.
سپس باید مطمئن شویم که آیکون ما صرفنظر از این که اپلیکیشن روی کدام دستگاه اجرا شده است، در مرکز صفحه باقی میماند. به این منظور در ناوبری سمت راست، آیکون پنجم از بالا (که شبیه خط کش است) را انتخاب کنید.
درون بخش Autoresizing باید خطوط قرمز بیرون را غیرفعال و خطوط قرمز درونی را فعال کنید. بدین ترتیب تصویر میتواند صرفنظر از این که ابعاد صفحه چه قدر است در مرکز آن بماند.
بدین ترتیب نتیجه زیر به دست میآید:
اینک باید به بررسی مشکل چشمک زدن صفحه سفید بپردازیم.
اما قبل از آن باید بفهمیم دلیل این مسئله چیست. این وضعیت زمانی اتفاق میافتد که جاوا اسکریپت در حال بارگذاری است و bridge مقداردهی اولیه میشود. یا دستکم این توضیحی است که ما به آن رسیدهایم. صفحه آغازین زمانی نمایش مییابد که اپلیکیشن در حال بالا آمدن است (React Native). سپس هنگامی که React Native مقداردهی میشود آن صفحه سفید را میبینیم، بنابراین باید صفحه آغازین را مقداری بیش از آنچه که لازم است روی صفحه حفظ کنیم. بدین منظور از react-native-splash-screen استفاده میکنیم. ابتدا این پکیج را نصب کرده و آن را لینک کنید:
yarn add react-native-splash-screen@3.0.6 react-native link react-native-splash-screen
سپس باید پکیج را پیکربندی کنیم. به این منظور در Xcode فایل AppDelegate.m را باز میکنیم.
سپس "import “SplashScreen.h# را با ایمپورتهای دیگر اضافه میکنیم و در ادامه ;[SplashScreen show] را در متد didFinishLaunchingWithOptions درست بالاتر از ;return YES اضافه میکنیم.
در نهایت در App.js باید به صفحه آغازین اعلام کنیم که وقتی اپلیکیشن ما آماده شد پنهان شود. این کار را در قلاب چرخه عمر componentDidMount انجام میدهیم.
1import SplashScreen from 'react-native-splash-screen';
2
3export default class App extends Component {
4 componentDidMount() {
5 SplashScreen.hide()
6 }
7
8 ...
9}
اینک ظاهر آن بهبود زیادی یافته است. در ادامه میخواهیم وقتی اپلیکیشن در صفحه آغازین قرار دارد، رنگ نوار وضعیت به صورت روشن در آید. به این منظور Info.plist را در Xcode باز کنید و یک ردیف جدید به آن بیفزایید. در این ردیف کلید باید به صورت UIStatusBarStyle و مقدار (رشتهای) به صورت UIStatusBarStyleLightContent باشد.
بدین ترتیب نتیجه مناسب زیر به دست میآید:
افزودن صفحه آغازین به اندروید
بخش اندروید بسیار پیچیدهتر از iOS است، زیرا باید دو صفحه آغازین ایجاد کنیم. یکی به وسیله react-native-splash-screen استفاده میشود و دیگری پیش از آن که اپلیکیشن inflate شود مورد استفاده قرار میگیرد.
نخستین کاری که باید انجام دهیم این است که فایلهای تصویر را که قبلاً دانلود کردهایم به دایرکتوریهای mipmap در پروژه اندروید اضافه کنیم. اندروید چگالیهای پیکسلی متفاوت را به روشی متفاوت از iOS مدیریت میکند و از این رو باید برخی تغییرات در تصاویر ایجاد کنیم.
قبل از هر چیز پوشههای mipmap در android/app/src/main/res قرار دارند و چگالی پیکسلی تصاویر هر کدام بر اساس نام پوشه متفاوت است. تصاویر ما باید به صورت زیر قرار گیرند:
- mipmap-mdpi = icon.png
- mipmap-hdpi = icon@2x.png
- mipmap-xhdpi = icon@3x.png
- mipmap-xxhdpi = icon@3x.png
زمانی که فایلها در پوشههای مربوطه قرار گرفتند باید نام آنها را به icon.png تغییر دهید.
سپس پا را فراتر گذارده و صفحه آغازین را که هنگام لانچ شدن اولیه اپلیکیشن از آغاز سرد نمایش مییابد، ایجاد میکنیم.
ابتدا یک فایل به نام background_splash.xml file در android/app/src/main/res/drawable ایجاد میکنیم. احتمالاً باید دایرکتوری مربوطه را نیز بسازید. کد زیر را به فایل اضافه کنید:
1<?xml version="1.0" encoding="utf-8"?>
2<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3
4 <item
5 android:drawable="@color/blue"/>
6
7 <item
8 android:width="200dp"
9 android:height="200dp"
10 android:drawable="@mipmap/icon"
11 android:gravity="center" />
12
13</layer-list>
کاری که در اینجا انجام میدهیم این است که یک فهرست لایهها به نام layer-list تنظیم میکنیم و سپس یک رنگ پسزمینه تعیین میکنیم و در نهایت آیکون خود را رندر میکنیم. این آیکون روی صفحه 200dp عرض و ارتفاع خواهد داشت.
سپس فایلی به نام colors.xml در android/app/src/main/res/values میسازیم که در آن رنگ آبی خود را تعریف میکنیم.
1<?xml version="1.0" encoding="utf-8"?>
2<resources>
3 <color name="blue">#4F6D7A</color>
4</resources>
در ادامه یک مقدار جدید به نام SplashTheme در android/app/src/main/res/values/styles.xml میسازیم.
1<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
2 <item name="android:windowBackground">@drawable/background_splash</item>
3 <item name="android:statusBarColor">@color/blue</item>
4</style>
به آن اعلام خواهیم کرد که از background_splash که به صورت پسزمینه پنجره تعریف کردهایم استفاده کند و همچنین اعلام میکنیم که از رنگ آبی برای نوار وضعیت بهره بگیرد. ما تلاش میکنیم اپلیکیشن واقعی را تا حد امکان در اینجا شبیهسازی کنیم و از این رو تغییر نوار وضعیت را طراحی میکنیم.
حال که به اینجا رسیدهایم پا را فراتر گذارده و مطمئن میشویم که StatusBar پیشفرض قالب اصلی اپلیکیشن ما دارای رنگ پیشفرض صحیحی است. بدین ترتیب فایل styles.xml باید به صورت زیر باشد:
1<resources>
2
3 <!-- Base application theme. -->
4 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
5 <!-- Customize your theme here. -->
6 <item name="android:statusBarColor">@color/blue</item>
7 </style>
8
9 <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
10 <item name="android:windowBackground">@drawable/background_splash</item>
11 <item name="android:statusBarColor">@color/blue</item>
12 </style>
13
14</resources>
اکنون باید به اپلیکیشن خود اعلام کنیم که در زمان مقدر دهی اولیه از SplashTheme استفاده کند. این کار را در AndroidManifest.xml انجام میدهیم. درون <application></application> کد زیر را اضافه میکنیم:
1<activity
2 android:name=".SplashActivity"
3 android:theme="@style/SplashTheme"
4 android:label="@string/app_name">
5 <intent-filter>
6 <action android:name="android.intent.action.MAIN" />
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9</activity>
و MainActivity را طوری تغییر میدهیم که به صورت زیر در آید. توجه ویژهای به android:exported="true" که اضافه میکنیم داشته باشید:
1<activity
2 android:name=".MainActivity"
3 android:label="@string/app_name"
4 android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
5 android:windowSoftInputMode="adjustResize"
6 android:exported="true"
7/>
بدین ترتیب فایل AndroidManifest.xml به صورت زیر درمیآید:
1<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 package="com.splashexample"
3 android:versionCode="1"
4 android:versionName="1.0">
5
6 <uses-permission android:name="android.permission.INTERNET" />
7 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
8
9 <uses-sdk
10 android:minSdkVersion="16"
11 android:targetSdkVersion="22" />
12
13 <application
14 android:name=".MainApplication"
15 android:allowBackup="true"
16 android:label="@string/app_name"
17 android:icon="@mipmap/ic_launcher"
18 android:theme="@style/AppTheme">
19
20 <activity
21 android:name=".SplashActivity"
22 android:theme="@style/SplashTheme"
23 android:label="@string/app_name">
24 <intent-filter>
25 <action android:name="android.intent.action.MAIN" />
26 <category android:name="android.intent.category.LAUNCHER" />
27 </intent-filter>
28 </activity>
29
30 <activity
31 android:name=".MainActivity"
32 android:label="@string/app_name"
33 android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
34 android:windowSoftInputMode="adjustResize"
35 android:exported="true"
36 />
37
38 <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
39 </application>
40
41</manifest>
اکنون باید یک فایل به نام SplashActivity.java ایجاد کنیم.
هدف از این فایل SplashActivity.java آن است که به MainActivity فوروارد شود. محتوای آن چنین است:
1package com.splashexample; // make sure this is your package name
2
3import android.content.Intent;
4import android.os.Bundle;
5import android.support.v7.app.AppCompatActivity;
6
7public class SplashActivity extends AppCompatActivity {
8 @Override
9 protected void onCreate(Bundle savedInstanceState) {
10 super.onCreate(savedInstanceState);
11
12 Intent intent = new Intent(this, MainActivity.class);
13 startActivity(intent);
14 finish();
15 }
16}
اکنون فرض میکنیم که همه چیز به درستی تنظیم شده است. اگر اپلیکیشن را اجرا کنید و سپس از آن خارج شوید (تا یک آغاز سرد داشته باشیم)، باید چیزی مانند زیر ببینید:
این وضعیت مناسبی است، اما آن صفحه سفید هنوز دیده میشود. البته اصلاح آن به سادگی iOS نیست، اما چندان دشوار هم نیست. اگر react-native-splash-screen را قبلاً نصب نکردهاید، آن را نصب کرده و لینک کنید.
yarn add react-native-splash-screen@3.0.6 react-native link
سپس باید سمت اندروید نیتیو را پیکربندی کنید. در فایل MainActivity.java کد زیر را اضافه کنید:
1package com.splashexample; // this should be your package name
2
3import com.facebook.react.ReactActivity;
4import org.devio.rn.splashscreen.SplashScreen; // import this
5import android.os.Bundle; // import this
6
7public class MainActivity extends ReactActivity {
8 @Override
9 protected void onCreate(Bundle savedInstanceState) {
10 SplashScreen.show(this); // here
11 super.onCreate(savedInstanceState);
12 }
13
14 ...
15}
سپس App.js را در اپلیکیشن خود طوری پیکربندی کنید که به محض بارگذاری شدن اپلیکیشن، صفحه آغازین را ببندد.
1import SplashScreen from 'react-native-splash-screen';
2
3export default class App extends Component {
4 componentDidMount() {
5 SplashScreen.hide()
6 }
7
8 ...
9}
سپس باید فایلی به نام launch_screen.xml (حتماً باید به این نام باشد) درون android/app/src/main/res/layout ایجاد کنید که عنصر ریشهاش LinearLayout باشد.
اندروید استودیو اینترفیسی بسیار شبیه به اینترفیسساز Xcode دارد، اما در این راهنما ترجیح میدهیم، عناصر را مستقیماً تغییر دهیم. ابتدا gravity عنصر LinearLayout را طوری تنظیم میکنیم که در مرکز قرار گیرد و رنگ پسزمینهاش نیز آبی باشد. بقیه قسمتها به صورت پیشفرض میماند.
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:background="@color/blue"
7 android:gravity="center">
8</LinearLayout>
سپس ImageView را طوری رندر میکنیم که آیکونی درون LinearLayout نمایش دهد.
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:background="@color/blue"
7 android:gravity="center">
8 <ImageView
9 android:layout_width="200dp"
10 android:layout_height="200dp"
11 android:layout_marginTop="24dp"
12 android:src="@mipmap/icon"
13 />
14</LinearLayout>
نکاتی در خصوص مشخصههای روی ImageView
- android:layout_width و android:layout_height – ارتفاع و عرض را تعیین میکنند. این مقادیر باید همانند مقادیری باشند که در background_splash.xml تنظیم شدهاند.
- android:layout_marginTop – این ارتفاع نوار وضعیت است. اگر این مقدار را نادیده بگیریم، آیکونها دقیقاً در همان نقطه مورد نظر نخواهند بود و یک پرش در زمان تغییر صفحه آغازین را شاهد خواهید بود.
- "android:src="@mipmap/icon – تصویری است که باید رندر شود.
در نهایت درون فایل colors.xml کد زیر را اضافه کنید:
1<color name="primary_dark">#4F6D7A</color>
در غیر این صورت اپلیکیشن کرش میکند. این یک باگ در react-native-splash-screen است و احتمالاً در نسخههای بعدی رفع خواهد شد.
بدین ترتیب به پایان این مقاله میرسیم. امیدواریم این راهنما برای شما کاربردی بوده باشد.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای جاوا اسکریپت
- آموزش ساخت پروژه با فریم ورک React Native
- مجموعه آموزشهای برنامهنویسی
- دسترسی به موقعیت جغرافیایی در React Native و Expo — راهنمای کاربردی
- یازده کتابخانه کامپوننت کاربردی React Native برای سال ۲۰۱۹ — راهنمای جامع
==