flutter でスプラッシュウインドウを使う(flutter_native_splash)
iOS側だとスプラッシュウインドウは必須みたいなのでこういうのははじめから入れておかないと後で辛くなるのでちょい調べた。未来にまたアプリを作る際の作業メモ。
イチから入れる方法は公式から出てるけど、スプラッシュウインドウのパッケージがあるみたいね。
環境は以下で確認してます。
% flutter --version Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git Framework • revision 77d935af4d (9 days ago) • 2021-12-16 08:37:33 -0800 Engine • revision 890a5fca2e Tools • Dart 2.15.1
pubspec.ymlに以下を入れてpub getします。最新バージョンは前述のページで確認してください。2022/01現在、1.3.3。
dev_dependencies: flutter_native_splash: ^1.3.3
flutter_native_splash.yaml(スプラッシュウインドウの設定)
スプラッシュウインドウに表示する画像にこんなものを用意してみました。400*400ピクセルのpngファイルです。これを/assets/splash/splashicon.pngに保存しました。
これをアプリが使えるようにpubspec.ymlに登録します。
# To add assets to your application, add an assets section, like this: assets: - assets/splash/splashicon.png
各種設定はflutter_native_splash.yamlをプロジェクトのルートに作成し色々記載していきます。とりあえず以下の様な内容にしてみました。
flutter_native_splash: image: assets/splash/splashicon.png
設定した後以下のコマンドを打つと完了です。
flutter pub run flutter_native_splash:create
以下はコマンドのログです。
% flutter pub run flutter_native_splash:create [Android] Creating branding images [Android] Updating launch background(s) with splash image path... [Android] - android/app/src/main/res/drawable/launch_background.xml [Android] - android/app/src/main/res/drawable-v21/launch_background.xml [Android] Updating styles... [Android] - android/app/src/main/res/values/styles.xml [iOS] Creating images [iOS] Updating LaunchScreen.storyboard with width, and height [iOS] updating constraints with splash branding [iOS] Updating ios/Runner/Info.plist for status bar hidden/visible Web folder not found, skipping web splash update... Native splash complete. 👍 Now go finish building something awesome! 💪 You rock! 🤘🤩
flutter_native_splash.yaml には以下のようなオプションがあります。
color/ background_image
背景色か背景画像を指定します。いずれかの指定のみです。
color: "#42a5f5" # background_image: xxxxxx
image
スプラッシュウインドウに表示するアイコンです。中央に表示されます。フォーマットはpngオンリーでsized for 4x pixel densityだそうです。sized for 4x pixel densityが分からん・・・
branding/ branding_dark / branding_mode
企業ロゴみたいなものです。例えばimageで中央にアプリのアイコンを大きく表示して画面下に企業ロゴを表示するとか・・・
brandingにimageオプションと同様にイメージファイルへのパスを記載します。branding_darkはiOSのダークモード時に表示するイメージファイルです。いずれも今はimageオプションと同様にpngフォーマットのみ対応しています。
イメージファイルの場所はbranding_modeで指定します。bottom、bottomRight、bottomLeftが指定できます。(指定しないとbottom)
この値はAndroidのandroid_gravityとiOSのios_content_modeとは無関係です。
branding: assets/brand_dark.png branding_dark: assets/brand_dark.png branding_mode: bottom
color_dark/ background_image_dark/ image_dark: assets/splash-invert.png
上記color/ background_image、imageで書いたものがスプラッシュウインドウを表示する際に端末がダークモードの場合こちらの値になります。
android/ ios/ web
スプラッシュウインドウを生成するかどうかです。AndroidはたしかGooglePlayでリリースする際スプラッシュウインドウは必須ではないためこれをfalseにするなどでしょうか。
android: false ios: true web: false
android_gravity/ ios_content_mode/ web_image_mode
imageで設定した画像をどこに表示するか?を指定します。
android_gravityはbottom, center, center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal, fill_vertical, left, right, start, or top から指定しますが以下のGravityの値に準拠します。
Gravity | Android Developers
ios_content_modeはscaleToFill, scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight, bottomLeft, or bottomRightから指定しますが、以下のiOSのUIView.ContentModeに準拠します。
Apple Developer Documentation
web_image_modeはcenter, contain, stretch, and coverから指定します。特に指定しないと画面中央に表示されるようですね。
fullscreen
trueにすると画面上部にある通知バーも含むフルスクリーンで表示します。
info_plist_files
info.plistの名前を変更した場合、そのファイル名を指定します。iOS系の開発に疎いのでこのファイルを変更できるってことかな?
info_plist_files: - 'ios/Runner/Info-Debug.plist' - 'ios/Runner/Info-Release.plist'
flutter_native_splash.yamlを使用しないでの設定
MyApp#build()の変更
readmeページだとflutter_native_splash.yamlに設定を書いて云々とありますが、installページではpubspec.ymlに依存関係書いてあとはパッケージインポートでExampleページではflutter_native_splash.yamlは特に関係ない感じで書いてあります。
flutter_native_splash.yamlで全部設定しても良いですし、コード上で書いてもいいという事でしょうか。例えば自由にスプラッシュウインドウのレイアウトを組んで表示する、などが考えられます。
Flutterプロジェクト作成直後のmain.dartはMyApp#build()でStatefullWidgetのMyHomePageインスタンスを返すようになっていますが、ここでローディング中ならスプラッシュ用のStatelessWidgetを返すように変更します。
以下はFlutterプロジェクト作成直後のmain.dartのMyAppとbuild()とスプラッシュ対応版の比較です。作成直後のMyApp#build()では単純にMaterialAppを返していますが、スプラッシュ対応版はローディング中ならsplash()メソッドを呼び出しスプラッシュ用のStatelessWidgetを返す様になっています。
プロジェクト作成直後ならMyApp#build()全体をコピペでいいみたいです。
import 'package:flutter_native_splash/flutter_native_splash.dart'; ...省略 class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } }
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return FutureBuilder( future: Init.instance.initialize(), builder: (context, AsyncSnapshot snapshot) { // Show splash screen while waiting for app resources to load: if (snapshot.connectionState == ConnectionState.waiting) { return const MaterialApp(home: Splash()); } else { // Loading is done, return the app: return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } }, ); } }||< *** 実際のSplashメソッド 以下はExampleページから引っ張ってきたコードですが、Splashウインドウのウィジェット定義部分です。あとはmain.dartの下にこれをコピペします。 自由にレイアウトを組む場合はこのSplash#build()で自由なWidgetを返すようにします。 >|| class Splash extends StatelessWidget { const Splash({Key? key}) : super(key: key); @override Widget build(BuildContext context) { bool lightMode = MediaQuery.of(context).platformBrightness == Brightness.light; return Scaffold( backgroundColor: lightMode ? const Color(0xffe1f5fe) : const Color(0xff042a49), body: Center( child: lightMode ? Image.asset('assets/splash.png') : Image.asset('assets/splash_dark.png')), ); } } class Init { Init._(); static final instance = Init._(); Future initialize() async { // This is where you can initialize the resources needed by your app while // the splash screen is displayed. Remove the following example because // delaying the user experience is a bad design practice! await Future.delayed(const Duration(seconds: 3)); } }
flutter pub run flutter_native_splash:createの結果
以下は色々とオプションをガチャガチャ変更してflutter pub runした結果ですがプロジェクト内に色々ファイルが作られたり更新されたりするようですね。という情報でした。
new file: android/app/src/main/res/drawable-hdpi/branding.png new file: android/app/src/main/res/drawable-hdpi/splash.png new file: android/app/src/main/res/drawable-mdpi/branding.png new file: android/app/src/main/res/drawable-mdpi/splash.png new file: android/app/src/main/res/drawable-v21/background.png modified: android/app/src/main/res/drawable-v21/launch_background.xml new file: android/app/src/main/res/drawable-xhdpi/branding.png new file: android/app/src/main/res/drawable-xhdpi/splash.png new file: android/app/src/main/res/drawable-xxhdpi/branding.png new file: android/app/src/main/res/drawable-xxhdpi/splash.png new file: android/app/src/main/res/drawable-xxxhdpi/branding.png new file: android/app/src/main/res/drawable-xxxhdpi/splash.png new file: android/app/src/main/res/drawable/background.png modified: android/app/src/main/res/drawable/launch_background.xml modified: android/app/src/main/res/values/styles.xml new file: ios/Runner/Assets.xcassets/BrandingImage.imageset/Contents.json new file: ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json new file: ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png modified: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json modified: ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png modified: ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png modified: ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png modified: ios/Runner/Base.lproj/LaunchScreen.storyboard modified: ios/Runner/Info.plist