【Android】スプラッシュ画面実装

はじめまして、初投稿です！
まだまだ未熟な学生プログラマですが、頑張ります。

## スプラッシュを考える
さて、アプリをつくるぞー、となった時にまず考えてしまうのがスプラッシュ画面です。

これまでボタンを配置するように`setContentView()`で表示していました。

とくに考えることもなく実装できたので、これでいいやと思ってました。

しかしそれでは**ユーザー体験が悪くなる！**と有識者:mortar_board:からお聞きして、心機一転、`setTheme()`でのスプラッシュ実装をするようになりました。

そうなるまでの紆余曲折をレポート:memo:します！

## setContentView()でやってること
いつものやつです。レイアウトファイルを読み込んで、Viewを配置してくれます。
`setTheme()`との大きな違いは、表示するものがViewであることだと思います。

## setTheme()でやっていること
そのActivityのテーマをセットしてくれます。`setContentView()`とのちがいは、アプリ起動した瞬間の挙動です。
通常、`setContentView()`では
>[アプリ起動]->[onCreate]->[Themeの確定]->[setContentView]->スプラッシュのView表示

この[Themeの確定]でデフォルトだと真っ白(黒)な画面ですので、アプリ起動すると一瞬それが見えます。起動時の処理が重いと、アプリ起動してからしばらくそれが見れるはずです。

これを`setTheme()`を使うと、
>[アプリ起動]->[onCreate]->[setTheme]->スプラッシュ画面表示->[setContentView]->View表示

となり、起動時の処理に左右されず、アプリ起動してからスプラッシュ画面までの反応が早いです。これでユーザーの体験がよくなるわけですね。

## 注意点
`setTheme()`でスプラッシュ画面を実装すると、Activityの画面遷移のようなアニメーションが適用されなくなります。

## 実装例
@yamikoo@github 様の記事を参考にさせていただきました。
私が実装を試した際にハマった点もふまえて記事にいたします。
<https://qiita.com/yamikoo@github/items/c82ea335968709a9d32a>

おおまかには

* drawable内に新規XMLファイル作成
* styles.xmlの編集
* Manifestファイルの編集
* Activityの編集

が必要です。

## 手順①　drawable内に新規XMLファイルをつくる
res/drawableに新しくXMLファイルを作ります。

```xml:splash.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:opacity="opaque"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <item
        android:drawable="@color/splashBackground"/>

    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/splash_img" />
    </item>

</layer-list>

```

## 手順②　styles.xmlの編集
res/values/styles.xmlに新しくスタイルを追加します。今回は**SplashTheme**としました。

```xml:styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="SplashTheme" parent="AppTheme">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>

</resources>


```

## 手順③　Manifestファイルの編集
先ほど追加したスタイルを設定します。

```xml:AndroidManifest.xml一部抜粋

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/SplashTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

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

```

## 手順④　Activityの編集
ポイントしては、`Thread.sleep(1000)`で一秒間スプラッシュ画面が出るように設定しています。そして一秒後に元のテーマに戻しています。私の場合は元々`R.style.AppTheme_NoActionBar`でした。

```java:MainActivity.java一部抜粋

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // splash
    try {
        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    setTheme(R.style.AppTheme_NoActionBar);
    setContentView(R.layout.activity_main);

    /**** Do something...　****/
}

```

これで実装できました。

## ハマったところ
### スプラッシュ画面のサイズがおかしい(おかしくない)
今回スプラッシュ用にPNG形式(265x470)を用意しました。
ImageViewであればプロパティで`match_parent`とかやれば、画面いっぱいに画像を出してくれましたが、そうはいきません。

作ったXMLファイルをもう一度見ていただければわかりますが、画像はbitmapとして定義されています。このためサイズ通り表示されます。

```xml:splash.xml一部抜粋

<bitmap
    android:gravity="center"
    android:src="@drawable/splash_img" />

```

私は265x470の画像を使ったので、画面いっぱいに表示されませんでした。そうすると、余白ができてしまいます。

これを回避する方法がさまざま検討されているようですが、結局ムリそうです。
<https://stackoverflow.com/questions/23079355/android-bitmap-image-size-in-xml>
何かいい方法がありましたら教えてください。:sob:

## 回避方法(?)
なにも回避できていませんが、私はこうしました。
もう一度splash.xmlを見てください。

```xml:splash.xml抜粋

<item
    android:drawable="@color/splashBackground"/>

```

colors.xmlに新しくsplashBackgroundを定義して、余白の色を設定しました。
こうするとそれっぼく見えます。

## さいごに
ユーザー体験を意識するのは大変ですが、少しでも良くしていきたいですね。

## 参考
**@yamikoo@github 様**
タイトル：Android スプラシュ画面の実装
<https://qiita.com/yamikoo@github/items/c82ea335968709a9d32a>

<https://stackoverflow.com/questions/23079355/android-bitmap-image-size-in-xml>