🍼

Flutter でガイダンス(チュートリアル)を作る

2021/10/09に公開

ガイダンス(チュートリアル)とは

一見のユーザーはアプリについての理解度がないので、ガイダンス(チュートリアル)があると親切です。
そこで今回は Flutter でのガイダンス作成に便利なライブラリを見つけたのでご紹介します。

flutter_intro

flutter_intro は Flutter でのガイダンス作成に便利なライブラリです。アニメーション付きで実装できるのでオススメです。
https://pub.dev/packages/flutter_intro

インストール方法などは上記のリンクから確認してください。

サンプルコード

今回はflutter_intro の Exampleのコードから解説します。

デフォルト アドバンス カスタム

Intro

ガイダンスを再生するオブジェクトです。ガイダンスのステップ数やガイダンスを構成する Builder を設定します。

Default Theme

デフォルトだと下記のようになります。
texts に各ステップごとのテキストを設定します。

intro = Intro(
  stepCount: 4,
  maskClosable: true,
  onHighlightWidgetTap: (introStatus) {
    print(introStatus);
  },

  /// use defaultTheme
  widgetBuilder: StepWidgetBuilder.useDefaultTheme(
    texts: [
      'Hello, I\'m Flutter Intro.',
      'I can help you quickly implement the Step By Step guide in the Flutter project.',
      'My usage is also very simple, you can quickly learn and use it through example and api documentation.',
      'In order to quickly implement the guidance, I also provide a set of out-of-the-box themes, I wish you all a happy use, goodbye!',
    ],
    buttonTextBuilder: (currPage, totalPage) {
      return currPage < totalPage - 1 ? 'Next' : 'Finish';
    },
  ),
);
intro.setStepConfig(
  0,
  borderRadius: BorderRadius.circular(64),
);

Advanced Theme

アドバンスだと下記のようになります。
ガイダンスのステップ毎の Widget をカスタマイズできます。

intro = Intro(
  stepCount: 4,
  maskClosable: false,
  onHighlightWidgetTap: (introStatus) {
    print(introStatus);
  },

  /// useAdvancedTheme
  widgetBuilder: StepWidgetBuilder.useAdvancedTheme(
    widgetBuilder: (params) {
      return Container(
        decoration: BoxDecoration(
          color: Colors.red.withOpacity(.6),
        ),
        child: Column(
          children: [
            Text(
              '${params.currentStepIndex + 1}/${params.stepCount}',
              style: TextStyle(
                color: Colors.green,
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
            Row(
              children: [
                ElevatedButton(
                  onPressed: params.onPrev,
                  child: Text('Prev'),
                ),
                ElevatedButton(
                  onPressed: params.onNext,
                  child: Text('Next'),
                ),
                ElevatedButton(
                  onPressed: params.onFinish,
                  child: Text('Finish'),
                ),
              ],
            ),
          ],
        ),
      );
    },
  ),
);
intro.setStepConfig(
  0,
  borderRadius: BorderRadius.circular(64),
);

Custom Theme

おそらくカスタムが一番利用すると思います。
Builder 関数を自作して実装します。
アドバンスと比較するとカスタムの利点は Widget の位置を自由に設定できることだと思います。

intro = Intro(
  stepCount: 4,

  maskClosable: true,

  /// implement widgetBuilder function
  widgetBuilder: customThemeWidgetBuilder,
);

Widget customThemeWidgetBuilder(StepWidgetParams stepWidgetParams) {
  List<String> texts = [
    'Hello, I\'m Flutter Intro.',
    'I can help you quickly implement the Step By Step guide in the Flutter project.',
    'My usage is also very simple, you can quickly learn and use it through example and api documentation.',
    'In order to quickly implement the guidance, I also provide a set of out-of-the-box themes, I wish you all a happy use, goodbye!',
  ];
  return Padding(
    padding: EdgeInsets.all(
      32,
    ),
    child: Column(
      children: [
        SizedBox(
          height: 40,
        ),
        Text(
          '${texts[stepWidgetParams.currentStepIndex]}${stepWidgetParams.currentStepIndex + 1} / ${stepWidgetParams.stepCount}】',
          style: TextStyle(
            color: Colors.white,
            fontSize: 16,
          ),
        ),
        Row(
          children: [
            ElevatedButton(
              onPressed: stepWidgetParams.onPrev,
              child: Text(
                'Prev',
              ),
            ),
            SizedBox(
              width: 16,
            ),
            ElevatedButton(
              onPressed: stepWidgetParams.onNext,
              child: Text(
                'Next',
              ),
            ),
            SizedBox(
              width: 16,
            ),
            ElevatedButton(
              onPressed: stepWidgetParams.onFinish,
              child: Text(
                'Finish',
              ),
            ),
          ],
        ),
      ],
    ),
  );
}

StepWidgetParams について

StepWidgetParams はガイダンスの進行状況を保持しているパラメータです。
以下のようなものがあります。

  • currentStepIndex は現在のステップ数(インデックス)
  • stepCount は全体のステップ数
  • onPrev / onNext / onFinish はそれぞれ 前のステップ / 次のステップ / 終了 へ進行

ガイダンスの対象 Widget を設定

intro を生成したらガイダンスの対象 Widget を設定します。
build のタイミングでガイダンス対象 Widget に intro の key を設定します。

FloatingActionButton(
  /// 1st guide
  key: intro.keys[0],
  child: Icon(
    Icons.play_arrow,
  ),
  ...

こんな感じで intro.keys を設定します。 intro.keys に指定するインデックスはガイドする順番です。

Widget build(BuildContext context) {
  return WillPopScope(
    child: Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Container(
          padding: EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(
                width: 100,
                child: Placeholder(
                  /// 2nd guide
                  key: intro.keys[1],
                  fallbackHeight: 100,
                ),
              ),
              SizedBox(
                height: 16,
              ),
              Placeholder(
                /// 3rd guide
                key: intro.keys[2],
                fallbackHeight: 100,
              ),
              SizedBox(
                height: 16,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  SizedBox(
                    width: 100,
                    child: Placeholder(
                      /// 4th guide
                      key: intro.keys[3],
                      fallbackHeight: 100,
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        /// 1st guide
        key: intro.keys[0],
        child: Icon(
          Icons.play_arrow,
        ),
        onPressed: () {
          intro.start(context);
        },
      ),
    ),
    ...
  );
}

ガイダンスの開始

ここで下準備は終わりました。
あとは intro.start(context) でガイダンスを開始します。


void initState() {
  super.initState();
  Timer(
    Duration(
      milliseconds: 500,
    ),
        () {
      /// start the intro
      intro.start(context);
    },
  );
}

開放処理

あとは解放処理を忘れずに。

IntroStatus introStatus = intro.getStatus();
if (introStatus.isOpen) {
  // destroy guide page when tap back key
  intro.dispose();
}

おしまい

ガイダンス(チュートリアル)を実装するのは結構めんどくさいですが、 flutter_intro を使うと割と手軽に実装できそうです。

良かったらこちらもどうぞ

Discussion