flutterにスプラッシュ画面を追加する話


vuetifyで作ったテスト管理ツールが、なんとなく形になったので、
ずっとやろうと思っていたFlutterに手を出したのですが。
Flutterの思想を理解するのにめちゃくちゃ苦しみました・・・。

環境

  • Windows(10)
  • Flutter(2.10.2)
    • Dart(2.16.1)
    • flutter_native_splash(^2.1.2+1)

事前準備

Flutterプロジェクトが作成できること前提としています。

  • VSCode
    • Flutterの拡張機能
    • AndroidStudio

手順

1. Flutterプロジェクト作成

下記コマンドを使用してサンプルのプロジェクトを作ります。

flutter create flutter_splash_sample

下記コマンドを使用して起動確認

cd flutter_splash_sample
flutter run

こんな感じでサンプルが起動したらOKです。

2. flutter native splashのインストール

flutter native splashを使って作っていくので、まずはパッケージのインストールします。

配布元にあるように下記、コマンドを実行してパッケージの最新版を導入します。
flutter_native_splash

flutter pub add flutter_native_splash

余談ですけど、flutter pub addコマンドとpubspec.yamlに記載してflutter pub getするのだとどっちがいいのだろう。
やったことないけど、pubspec.yamlに書くとバージョン指定可能っぽいから最新版以外使うならyaml記載なのかな。と勝手に解釈している今日この頃。

3. splashで表示する内容を記載

今回は背景色だけ変えます。

flutter_native_splash:
  color: "0021FF"
  # image: "assets/images/splash.png"
  # ↑画像表示させるときは任意のフォルダに画像を格納してパスを記載する

yamlを変更したらflutter pub getして変更内容を反映します。

4. splash作成

(この手順を抜かしててSplashがでない・・・って嘆いてた過去の自分へ。)
下記コマンドを実行して、splashを作成します。

flutter pub run flutter_native_splash:create

こんなリザルトがでたら成功です。

~中略~
╔════════════════════════════════════════════════════════════════════════════╗
║                                 WHAT IS NEW:                               ║
╠════════════════════════════════════════════════════════════════════════════╣
║ You can now keep the splash screen up while your app initializes!          ║
║ No need for a secondary splash screen anymore. Just use the remove()       ║
║ method to remove the splash screen after your initialization is complete.  ║
║ Check the docs for more info.                                              ║
╚════════════════════════════════════════════════════════════════════════════╝

Native splash complete. 👍
Now go finish building something awesome! 💪 You rock! 🤘🤩

で、枠の中の言葉に従って最後の手順です。

5. mainのファイルを編集

void main()が記載してあるファイルに追記していきます。
作ったそのままなら、main.dartになります。

追加したところは『★』を記載します。

main.dart
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart'; // ★

void main() {
  // Start★
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
  // End★
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  // Start★
  
  void initState() {
    super.initState();
    initialization();
  }

  void initialization() async {
    print('ready in 3...');
    await Future.delayed(const Duration(seconds: 1));
    print('ready in 2...');
    await Future.delayed(const Duration(seconds: 1));
    print('ready in 1...');
    await Future.delayed(const Duration(seconds: 1));
    print('go!');
    FlutterNativeSplash.remove();
  }
  // End★
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

etc.

スプラッシュを更新する時は、手順の『3.』と『4.』を行います。

あとがき

Android/iOSそれぞれで作らなくていいのは、すごくメリットですよね。
先述しましたが思想を理解するのに苦しみましたが、落ち着いて向き合えば、慣れてくるもんですね(笑)

あとは、Vueをやった時も思いましたが、開発を加速できるパッケージが豊富なのは助かります。

参考記事

Github