【Flutter入門】Flutterで簡単なTODOアプリを作る。statefulWidget使用

皆さんこんにちは。先日社内向け勉強会でFlutterのハンズオンをしました。その際にstatefulWidgetを使ってTODOアプリを作成しました。その解説を行います。最終的にはとても簡単なTODOアプリが完成します!
ソースコードは記事の最後に載せています。

Harumaki
Harumaki

Flutterを使ってTODOアプリを作成するよ。

それでは早速参ります。

完成系はこんな感じです。

機能としては以下です。

  • 右下のプラスアイコンをクリックしてTODOを追加できる
  • TODOに文字を入力できる。文字列の編集もできる。
  • TODOにチェックできる
  • TODOがチェック状態なら取り消し線にする

FlutterのWidgetという概念について

Flutterを作ったGoogleが提唱していることですが、"Everything is a Widget" すべてはWidgetということです。

ボタンでもテキストでも枠組みでも、全てWidgetというものです。簡単に言えばUIパーツといえるでしょうか。すべてWidgetクラスを継承しています。

Widgetの大まかな種類

こちらのサイトで紹介されていた画像です。わかりやすかったです。Widgetを4つの種類に分けて考えています。画面の部品パーツはそのうちの1つです。他に、アプリ全体に関するWidgetや、画面の土台になるWidgetや、パーツの並べ方に関するWidgetがあります。

スタイルシートでいうところの、marginやpositionなどもこのWidgetで表現します。

Widgetツリーについて

Widgetツリーについて簡単に説明をします。Web開発でいうとDOMツリーのようなものです。Flutterの内部にはWidgetツリーというものがあり、これが画面を形成しています。正確にはelementツリーを生成しているようですがここでは割愛します。

ルートには、MyAppがあります。これはDOMツリーでいうところdocumentのようなものでしょうか(?)。
その配下には、MaterialAppとScafoldがあり、画面の土台を形成しています。その下に、かく部品などがぶら下がっているイメージです。

Flutterでの状態管理の概念

モダンなjsフレームワークではstate管理機能があります。状態管理機能ですね。Flutterにもそれがあります。
初学者はまず、statelessWidgetと、statefulWidgetを使うようです。学習するにつれて、他に別のもので管理するようですが・・・。今回のTODOアプリではリストを追加したあとに、その追加したことを画面に反映させたいのでstatefulWidgetを使用します。

TODOアプリをコーディングしていく

さっそくTODOアプリを作っていきましょう。まずはソースコードを貼り付けちゃいます。コメントを適当に書いています。

↓main.dart

import 'package:flutter/material.dart';
import 'package:my_app/todo.dart';

void main() {
  // runApp関数でウィジェットツリーのルートとなる。
  runApp(const App());
}

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

  // stateLessWidget または stateFulWidgetを継承した場合は必ずbuildメソッドをオーバーライドしないといけない。
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomeScreen(),
    );
  }
}

// 途中で値が変わったらそれを反映させる必要があるのでStatefulWidgetを記載する
class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

// StatefulWidgetはWidgetにstateの概念をいれて拡張したもの
// StatefulWidgetはcreateStateメソッドを持ち、これがStateクラスを返す
  @override
  ////stateを継承している型
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  // 初めに3つTODOリストを作成
  final _todos = List.generate(
    3,
    (index) => ToDo(),
  );

  @override
  Widget build(BuildContext context) {
    // scaffold:足場
    return Scaffold(
        appBar: AppBar(
          title: const Text('Harumaki ToDo'),
          backgroundColor: const Color(0xFF388E3C),
        ),
        // ListView.builder()は基本的なリストを作成する
        body: ListView.builder(
          //生成する個数を指定する
          itemCount: _todos.length,

          // ↓itemBuilderの関数型の定義 Widget型を返す 引数にはこれら↓
          // IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
          // CheckboxListTileについて 公式 https://api.flutter.dev/flutter/material/CheckboxListTile-class.html
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              leading: Checkbox(
                value: _todos[index].checked,
                onChanged: (e) {
                  setState(() {
                    _todos[index].checked = e; //イベントeを受け取り反映 true, false
                  });
                },
              ),
              title: TextFormField(
                style: _todos[index].checked == true
                    ? const TextStyle(decoration: TextDecoration.lineThrough) // 取り消し線
                    : const TextStyle(color: Colors.black), // falseの時はただの黒色
              ),
            );
          },
        ),
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.add),
          backgroundColor: const Color(0xFF388E3C),
          onPressed: () {
            // setState()を呼び出すことで裏では再度buildメソッドを呼び出して変更された変数で再描画している
            setState(() {
              _todos.add(
                ToDo(),
              );
            });
          },
        ));
  }
}

↓todo.dart (TODOクラス)

import 'package:flutter/material.dart';

class ToDo {
  String title;
  bool? checked;

  ToDo([this.title = "", this.checked = false]);
}

上記、main.dartとtodo.dartがあれば今回のTODOアプリはできます。同じlibフォルダの中にmain.dartとtodo.dartはいれてください。

各コードの説明を簡単についてはコメントで記載しています。参考にしてみてください。

コードをコピペしてflutter run すれば簡単なTODOアプリが完成すると思います。

まとめ

今回はstatefulWidgetを使って簡単なTODOアプリを作成しました。

いろんなWidgetがあるので公式サイトをみてみてくださいね。
少しでもお役に立てたら幸いです。ではまた。最後まで読んでいただきありがとうございました。