しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

Androidアプリのスプラッシュ画面を実装する

アプリ起動時に表示されるスプラッシュ画面の実装を試してみました。
AndroidOS12から仕様が変わったようなので両方のパターンで作ってみます。

OS11以前

下の記事を参考に試してみました。
まずはwindowBackgroundを使う形で試してみます。

qiita.com

まずはdrawableにスプラッシュにしたいリソースを追加します。

次にスプラッシュ表示用のStyleを作成します。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Theme.MyApplication.TestStyle">
        <item name="android:windowBackground">@drawable/ic_android_black_24dp</item>
    </style>
</resources>

Styleを作ったらAndroidManifest.xmlでActivityのテーマに設定します。

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:label="@string/app_name"
    android:theme="@style/Theme.MyApplication.TestStyle">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

最後にActivity起動時に元々のThemeに変えるように設定します。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setTheme(R.style.Theme_MyApplication)

    }
}

縦横比はおかしいですがアプリ起動時にイラストを表示できました。
ちなみにActivity内でThemeを変えないとずっと背景にスプラッシュが出ることになります。

上記以外ですとActivityやFragmentを作ってアプリ起動時に一瞬表示させる方法などがあります。
この方法ですと動的な処理を入れる事も可能です。
今回は参考記事にあったようにActivityでスプラッシュを表示する方法を試してみます。

まずはbuild.gradleに一瞬スプラッシュを表示する時に使うライブラリを追加します。

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
}

次にSplashActivityを作成します。

スプラッシュ用にSplashActivityのレイアウトを整えます。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SplashActivity">

    <ImageView
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:src="@drawable/ic_android_black_24dp"
        android:layout_gravity="center" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

SplashActivityを作れたらAndroidManifest.xmlで起動時ActivityをSplashActivityに変更します。

<activity
    android:name=".SplashActivity"
    android:exported="true"
    android:label="@string/title_activity_splash"
    android:theme="@style/Theme.MyApplication.NoActionBar">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

最後にSplashActivityに一瞬表示されたらMainActivityを表示する処理を追加します。

class SplashActivity : AppCompatActivity() {
    private lateinit var binding: ActivitySplashBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivitySplashBinding.inflate(layoutInflater)
        setContentView(binding.root)

        CoroutineScope(Dispatchers.Main).launch {
            delay(500)
            val intent = Intent(this@SplashActivity, MainActivity::class.java)
            startActivity(intent)
            finish()
        }
    }
}

これで一瞬SplashActivityが出てから消えるようになりました。
ただ、こちらの方法ではスプラッシュが表示される前に一瞬白い画面が出るので注意が必要です。
windowBackgroundですと起動とほぼ同時にスプラッシュを出す事ができます。

OS12以降

次はOS12以降用のSplashScreen APIを使った方法を調べていきます。
こちらは下ページを参考にしました。

developer.android.com

OS12ですがデフォルトでスプラッシュ画像が表示されるようになります。
スプラッシュ画像は画面の真ん中にアプリアイコンがセットされたようなものです。

このスプラッシュ画像の背景色はandroid:windowSplashScreenBackgroundという要素を入れる事で変更できます。

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <item name="android:windowSplashScreenBackground" tools:targetApi="S">@color/teal_200</item>
    </style>
</resources>

アイコンとアイコンの背景色はwindowSplashScreenAnimatedIconとwindowSplashScreenIconBackgroundColorで変更します。
AnimatedVectorDrawableを指定すればアニメーション付きアイコンを表示する事も可能です。

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <item name="android:windowSplashScreenAnimatedIcon" tools:targetApi="S">@drawable/animation_icon</item>
        <item name="android:windowSplashScreenIconBackgroundColor" tools:targetApi="S">@color/teal_200</item>
    </style>
</resources>

アイコンですが下のようにサイズに関する制限があるので注意が必要です。

ブランド イメージ: 200 × 80 dp にする必要があります。
背景があるアプリアイコン: 直径 160 dp の円に収まる 240 x 240 dp にする必要があります。
背景がないアプリアイコン: 直径が 192 dp の円に収まる 288 x 288 dp にする必要があります。

スプラッシュの表示を伸ばしたい場合、addOnPreDrawListenerを利用します。
処理が終わるまで描画を止める事でスプラッシュを表示し続ける事ができます。

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val content = findViewById<View>(android.R.id.content)
        content.viewTreeObserver.addOnPreDrawListener(
            object : ViewTreeObserver.OnPreDrawListener {
                override fun onPreDraw(): Boolean {
                    // Check if the initial data is ready.
                    return if (/* 判定式を入れる */) {
                        // The content is ready; start drawing.
                        content.viewTreeObserver.removeOnPreDrawListener(this)
                        true
                    } else {
                        // The content is not ready; suspend.
                        false
                    }
                }
            }
        )
    }
}