たくさんの自由帳

Android でスプラッシュスクリーンのアイコンを動かす

投稿日 : | 0 日前

文字数(だいたい) : 7570

どうもこんにちは。
花鐘カナデ*グラム Chapter:2 花ノ香澄玲 攻略しました。(前作やってないので本筋あんまり分かってないけど)とにかくかわいかったです!

Imgur

ハイスペックでいい子すぎる

Imgur

↑ ここのシナリオすき、表情がころころ変わるのがいい

Imgur

そういえば最後の最後にあったあの意味深な文章は何だったんだろう、
3と4で回収するのかな(本筋もあんまり進まずに Chapter:2 終わってしまった)、、

Imgur

本題

Android 12 で入ったこのスプラッシュスクリーン、アニメーション付きのアイコンが使えるのですが、
なぜかそのスプラッシュスクリーンで使えるアニメーション付きアイコンの作り方が乗ってないので書きます。

こんなの、等倍速

等倍速だと速すぎるので0.5 倍速(これでもまだ速い気が)

AnimatedVectorDrawableを作るWebアプリを使うだけなのですが。。
結局このAnimated vector drawable、どうやって作るのが正攻法なのかがわからない、、、多分この方法は効率が悪い気がする、、、

個人的にはスプラッシュスクリーンアンチなのですが(アニメーションするくらいなら早く開けよお気持ち)、
Android 12から強制的にスプラッシュスクリーン付いてくるので、まあやるならアニメーションさせるか。って。

スプラッシュスクリーンで使うアイコンの作り方 公式

https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions

おことわり

多分この方法はとても非効率です。
おそらくどこか省略できる点があるはず。

環境

なまえあたい
PCWindows 10 Pro
InkscapeInkscape 1.1.1(最新版でいいはず)
LibreOfficeVersion: 7.0.4.2(最新版でいいはず)
言語Kotlin(多分Javaも行ける)

必要なソフトをダウンロード

なぜかInkscapeLibreOffice Drawが必要です。ほんとうはどっちかでSVGを書けばいいはずなのですが、InkscapesvgAndroid Studioに入れてDrawableにしてもなんかうまくいかないんですよね。
しかし、Inkscapeで保存したsvgLibreOffice Drawに入れて、別名保存したものをAndroid Studioに入れるとちゃんと反映される。何故か私の環境だと一回LibreOffice Drawを経由しないといけない。

なんでかな、バージョン古いからかな。

アイコンを描く

InkscapeでもLibreOffice Drawでも何でもいいのでSVGを書くアプリを開いてください。
まずSVG(Drawable)のサイズなのですが、私もよく知らない。ので私が作ってるときに使ってるサイズを貼っておくとこれです。正方形なので、縦横同じです。

Inkscape8.73000 mm
LibreOffice Draw0.90 cm
<svg> の属性width="8.73mm"

Inkscapeだとドキュメントのプロパティからサイズを変更できます。これ
Imgur

次にアイコンのサイズです、SVG(Drawable)のサイズと何が違うんだって話ですが、アイコン全体が表示されるわけではなく、真ん中を円形にくり抜いた分だけが表示されます。以下のドキュメントの画像がわかりやすいです。

https://developer.android.com/develop/ui/views/launch/splash-screen?#dimensions

アイコンを大きく書くと見切れてしまうし、小さすぎるとなんだか分からない。くり抜かれる範囲がどこか知りたいですよね、見切れちゃうと嫌ですからね。
というわけで試してみました。以下調査結果です。以下の四角形の範囲に収まれば(線踏むのは四隅じゃなければOK)大丈夫そうです。

数値でいうと、Inkscapeの場合は縦横2.115 mm ~ 6.615 mmの範囲内にアイコンを書けば、丸く切り抜かれても見切れたりしないはずです。

Imgur

実際に四角形を置いてみるとこう
Imgur

上記のように、わかりやすく四角形を置きたい場合、Inkscapeの場合は縦横4.500 mmの四角形を作って、それをページの真ん中に置くことで、その四角形の中なら見切れない、境界線代わりになります。
LibreOffice Drawでやりたい場合は0.45 cmの四角形を真ん中に置くと同様にできます。

Imgur

この四角形の中にアイコンを書いていきましょう。

書いた

あらかじめ時間によって表示したい(出し分けたい)図形はSVG上に存在させておく必要があります。多分。
いや、SVGのパスの変形が出来るっぽいんだけど難しそうで使ったことがない。

Imgur

保存する際は補助線としていた四角い図形を消しましょうね(まあこの後でも消せるけどここで消しちゃうで良い気がする)。

LibreOffice を経由する

Inkscapeで書いたSVGを保存したら、今度はLibreOffice Drawで開きます。
で、開いたら何もせずエクスポートを選び、SVGとして保存します。一応別名保存のがいいでしょう。

Imgur

なぜかこのLibreOffice Drawでエクスポートする工程をスキップするとうまくVectorDrawableに変換できません、、、

Imgur

また、このとき作ったSVGAndroid 11以下はスプラッシュスクリーンにAnimatedVectorDrawableが使えないので代わりにこれを使います。

AnimatedVectorDrawable を作る Web アプリ

こちらです。ありざいす!!!

https://shapeshifter.design/

開いたらさっき別名保存したSVGをインポートしましょう、ここです。ドラッグアンドドロップでもいいかもしれません。

Imgur

とりあえず時間経過で表示させてみる

というか私はこれしか使ったこと無いです。
適当なpathを選んで、ストップウォッチのアイコンを押して、strokeAlphaを選びます。

Imgur

次にfromValue0にしておきます。

Imgur

これで再生ボタンを押すと、、、?
時間経過でfromtからtoalphaが変化します!

Imgur

私が作ってきたスプラッシュスクリーンのアニメーションはこれの組み合わせがほとんどです、、

アニメーションの時間

ドキュメントによるとスプラッシュスクリーンのアニメーション最大秒数は1000msだそうですが、
せいぜいスプラッシュスクリーンのアニメーションは500msぐらいだと思います。

サーバー等の通信等でスプラッシュスクリーンを意図的に長く表示させる場合(ドキュメントにあるViewTreeObserver.OnPreDrawListenerを使う方法)を除き、500msぐらいが限界な気がする。あんまり長いとアニメーションの終了より先にActivityが起動しちゃう。

Imgur

また、これはAnimatedVectorDrawableの話ではなく、スプラッシュスクリーン都合の話だと思いますが、
0msから200msの間にアニメーションで変化させても認知できないです。(200msより前のアニメーションが何だったのか分からない)
アニメーションさせる場合は200msから500msに収めると良い気がします。

Imgur

アニメーションさせるまで消したい

線(stroke)の場合はstrokeAlpha、塗りつぶし(fill)の場合はfillAlpha0にしておくと、strokeAlphaのアニメーションまでは消しておくことが出来ます。

Imgur

アニメーション経過後はそのままアニメーションで変化した状態のが適用されます(手元で試している限り)

移動させたい、回転させたい、サイズを変えたい

translateXのようなものはありませんね。
これはpathだからで、groupを作り、その中にpathを入れることでtranslateXrotateが使えるようになります。

Imgur

というわけでgroupを作りますか、ここのNew group layerです。

Imgur

動かしたい図形たちをgroupの中に入れて、、、

Imgur

あとはお好きなものを。
移動させたいならtranslate、回転ならrotate、サイズ変更ならscaleです。

Imgur

保存する

shapeshifterwebアプリで開けるように保存しましょう。
ここのSaveを押すと、.shapeshifterでプロジェクトを保存できます。これを他の人に渡せば、他の人が開いたshapeshifterで続きの作業ができるわけです。
もしF5でリロードしたとしてもこのファイルで保存しておけば良いわけです。

Imgur

AnimatedVectorDrawable で吐き出す

それとは別にスプラッシュスクリーン用にAnimatedVectorDrawableが必要なので吐き出します。
これです。

Imgur

スプラッシュスクリーンを表示する準備をする

Android 12未満向けに、サポートライブラリがあります。
サポートライブラリ無しで直接Android 12以降で追加されたAPIを叩いても良いのですが、古い端末では利用できないので入れます。入れることでAndroid 6から最新までが一回の実装だけで済みます。

と言ってもドキュメント通りにライブラリを入れるだけです、

https://developer.android.com/develop/ui/views/launch/splash-screen/migrate

ライブラリをいれる

ついにデフォルトでGradle Version Catalogになりましたね、
単一モジュールでバージョンカタログ使ってもあれかと思ったのですが、マルチモジュールにしやすくするためかなって。

dependencies {
    implementation("androidx.core:core-splashscreen:1.0.1")
}

drawable-v31 フォルダを作る

drawableにアニメーションアイコンを格納するのですが、先述の通りアニメーションアイコンはAndroid 12(API 31)以降だけで、それ以前には動かないアイコンを置く必要があります。
バージョンによって分けるためにv31を作った感じです。

Imgur

後はそのフォルダにdrawbleを入れます。名前は合わせましょうね。

Imgur

themes.xml を書く

スプラッシュスクリーン用のテーマを書きます。
Jetpack Composeが主流の今、stylesとかthemesとか書かなくなったなあって。いい時代になりましたね。
View時代のMaterial Components ライブラリなんてテーマがすごく複雑で、一箇所変えたいだけなのに大変だった記憶が、、、あれ使いこなせた人いるのかな、調べてもわけわかめ。
てか結局styles.xmlthemes.xmlの違いが分からなかった。

背景色(windowSplashScreenBackground)ですが、色をcolors.xmlに書いて@color/で参照するべきです。ダークモードに対応できないので。

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <style name="Theme.KomaDroid" parent="android:Theme.Material.Light.NoActionBar" />
 
    <!-- スプラッシュスクリーン用テーマ -->
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
        <!-- 背景色 -->
        <item name="windowSplashScreenBackground">#4A5C92</item>
        <!-- アイコン -->
        <item name="windowSplashScreenAnimatedIcon">@drawable/komadroid_splash_icon</item>
        <!-- アニメーションの時間 -->
        <item name="windowSplashScreenAnimationDuration">500</item>
        <!-- スプラッシュスクリーンが終わった後のテーマ -->
        <item name="postSplashScreenTheme">@style/Theme.KomaDroid</item>
    </style>
</resources>

AndroidManifest.xml を編集

最初に起動するActivityandroid:themeを、android:theme="@style/Theme.App.Starting"になるように直します。

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

MainActivity を開く

最初に起動するActivityを開きます。たいていMainActivityだとは思いますが。
installSplashScreen()というKotlin拡張関数があるので、それを呼び出します。super.onCreateよりも前に。拡張関数がないJavaだとSplashScreen.installSplashScreenが使えるらしいです。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen() // super.onCreate よりも先
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            KomaDroidTheme {
                MainScreen()
            }
        }
    }
}
 

できた!!!

Q&A

Android 12 でスプラッシュスクリーンが出ない

ホーム画面のアイコンを押さないと表示されません。それ以外のルートで起動したら出ません。
(例:Android Studioの実行ボタン)

おわりに

差分貼っておきます。

https://github.com/takusan23/KomaDroid/commit/97ce9aeb45631426bf99f5f884f7fa5f5d4c0eb5

また、今回使ったShapeShifterのファイルも置いておきます。
https://github.com/takusan23/KomaDroid/blob/master/komadroid_splash_icon.shapeshifter

素材集
https://github.com/takusan23/AndroidSplashScreenDesignTemplate

以上でつ、お疲れ様でした88888