---
title: todo appをFlutterで作るハンズオン
tags:  #flutter #ハンズオン  
author: [Pregum](https://www.docswell.com/user/Pregum)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/3EKGQY9RJD.jpg?width=480
description: Flutterを使ったTodo app ハンズオン用のスライドです
published: August 14, 22
canonical: https://www.docswell.com/s/Pregum/ZJV71Z-2022-08-14-012322
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/3EKGQY9RJD.jpg)

Todo
アプリ ハンズオン
Todo
アプリハンズオン
by Flutter
pregum
pregum
1


# Page. 2

![Page Image](https://bcdn.docswell.com/page/L73NP9WG75.jpg)

アプリ ハンズオン
目次
Todo
最初に
とは？
Flutter とネイティブアプリとの違い
なぜ他のXPではなくFlutterなのか？
今日作るアプリについて
TodoApp 作成
( 時間があれば ) 、質疑応答
Flutter
pregum
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/87DWLGKNJG.jpg)

Todo
アプリ ハンズオン
最初に
今日はハンズオンに参加していただき、ありがとうございます。
1 点お願いがあります。
サンプルのカウンターアプリが起動ができていない方は
話している最初の10~15分程度でサンプルのカウンターアプリの起動
まで準備していただけますと
スムーズに進行できるかと思いますので、ご協力お願いします。
それではよろしくお願いします。
pregum
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/VJP923KNE8.jpg)

Todo
アプリ ハンズオン
動作環境
のバージョン: 3.0.5
Flutter のバージョンは flutter doctor -v で確認できます。
Flutter のバージョンをいじりたくない場合は
fvm を入れてバージョンを固定しましょう .
brew install fvm コマンド実行後、今回の作業フォルダで
fvm local 3.0.5 -f を実行すれば OK
参考サイト: https://zenn.dev/riscait/articles/flutter-versionFlutter
management
pregum
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/2EVMD4VYEQ.jpg)

Todo
アプリ ハンズオン
自己紹介
年生まれ
普段はKotlin, Swift,
TypeScript で開発しています
Flutter で個人アプリを
作っています
1995
pregum
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/57GGY1LW7L.jpg)

Todo
アプリ ハンズオン
Flutter
とは？
が開発中のクロスプラットフォーム(以降XP)開発が可能なフ
レームワークです。
今現在(2022/8/22)、iOS/Android/Web/Linux/macOS/Windowが
開発可能です。
Google
pregum
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/4EQXMDYQ7P.jpg)

Todo
アプリ ハンズオン
Flutter
とネイティブアプリとの違い
開発スピードと処理速度
項目
Flutter
パフォーマンス
若干遅い
開発速度 概ね１Platform分
検討されるケース 開発コスト削減
pregum
ネイティブアプリ
早い
OS 数に応じて遅くなる
native の機能が必要
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/KJ46VZWY71.jpg)

Todo
アプリ ハンズオン
なぜ他のXPではなくFlutterなのか？
色々ありますが以下が大きな要因です。
いい感じのUIが標準ライブラリで作れる
アプリを起動しながらレイアウトの微調整が可能
Debug ツールが使いやすい
対応プラットフォームが多い
UI のソースが Web 上で共有できる (DartPad)
pregum
8


# Page. 9

![Page Image](https://bcdn.docswell.com/page/LE1V3RYN7G.jpg)

Todo
アプリ ハンズオン
なぜ他のXPではなくFlutterなのか？
--&gt; UI
のソースがWeb上で共有できる(DartPad)
下記のurlからサンプルコードが実行可能
https://dartpad.dev/7942cc454f0937046632c7c61ea3e773
pregum
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/GEWLP11M72.jpg)

Todo
アプリ ハンズオン
実行結果
pregum
10


# Page. 11

![Page Image](https://bcdn.docswell.com/page/47ZMKPPME3.jpg)

Todo
アプリ ハンズオン
開発も全てDartPadで良いのでは
端末上では確認できない
複数ファイル必要な複雑なレイアウトは確認できない
MySQL などの DB や端末のセンサを使用するライブラリは使用不可
上記の点で実際の開発環境として使うのは厳しい
軽く挙動を見たい時に使うのが良さそう
pregum
11


# Page. 12

![Page Image](https://bcdn.docswell.com/page/YJ6NQMM5JV.jpg)

Todo
アプリ ハンズオン
今日作るアプリについて
pregum
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GJ55RZZGJ4.jpg)

Todo
アプリ ハンズオン
今日作るアプリについて
今日できるアプリ
https://github.com/Pregum/todo-app-hands-on-flutter
機能一覧
タスク作成機能
タスク編集機能
タスク削除機能
タスク完了チェック機能
pregum
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/LE3NP99PE5.jpg)

Todo
アプリ ハンズオン
アプリを作り始める前に
Flutter
のUIについて
のUIは全てウィジェット
テキスト
ボタン
チェックボックス
Flutter
etc...
pregum
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/8EDWLGG37G.jpg)

Todo
アプリ ハンズオン
Flutter
のUIについて
ウィジェットは大きく分けて2種類存在する
状態(State)を持つStateful Widget
setState() で状態を変更可能
状態(State)を持たないStateless Widget
setState() は使用不可
親ウィジェットや外部から受け取るデータによって更新可能
最初はStateful Widgetを使っておけばOK
pregum
15


# Page. 16

![Page Image](https://bcdn.docswell.com/page/V7P9233PJ8.jpg)

Todo
アプリ ハンズオン
Flutter
は宣言的UI
宣言的UI (React, SwiftUI, etc...)
String name = &#039;taro&#039;;
Center(
child: Text(&#039;Hello $name&#039;),
),
// -&gt; Hello taro
命令的UI (UIKit, WinForms, etc...)
text.frame = CGRect(
x: 50,
y: 50,
width: 50,
height: 50
)
text.text = &quot;taro&quot;
text.textAlignment = NSTextAlignment.Center
何を表示させるかを記述する。 レイアウトの配置からテキストの
文字列まで記述する。
pregum
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/2JVMD44VJQ.jpg)

Todo
アプリ ハンズオン
一言で表すと
宣言的UIは何をしたいかをコードで伝える (What)
命令的UIはどのようにしたいかをコードで伝える (How)
pregum
17


# Page. 18

![Page Image](https://bcdn.docswell.com/page/5EGGY111EL.jpg)

Todo
アプリ ハンズオン
Flutter
での描画
どのウィジェットを使用する場合でもレイアウトは build メソッドに
記述されています。
Text, ListView, Slider, Container, etc...
build
build
どのウィジェットでも
メソッドに記載されています。
レイアウトを確認したいときは
で検索すると良いです。
pregum
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/4JQXMDDNEP.jpg)

Todo
アプリ ハンズオン
【注意】画面の更新にはルールが存在する
画面の更新処理は必ず setState() メソッドの中に記述すること
OK
// :
Text(count)
// :
ヨシ！
//
setState(() {
count = count + 1;
});
pregum
NG
// :
Text(count)
// :
これでは画面に された値が反映されない
//
+1
count = count + 1;
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/K746VZZ3E1.jpg)

Todo
アプリ ハンズオン
Todo
アプリで使う主なウィジェット
MaterialApp
根本にとりあえず置いておくウィジェット
Scaffold
画面の大枠を作ってくれるウィジェット
ListView
いい感じにリスト形式で表示してくれる便利なウィジェット
Container
pregum
十徳ナイフのような万能ウィジェット
20


# Page. 21

![Page Image](https://bcdn.docswell.com/page/LJ1V3RRZEG.jpg)

Todo
アプリ ハンズオン
作成の流れ
プロジェクト作成
2. サンプルアプリ ( カウンターアプリ ) 動作確認
3. 1 つのタスクの UI 作成
4. リスト形式に並べる UI を作成
5. main.dart への配置
1.
pregum
21


# Page. 22

![Page Image](https://bcdn.docswell.com/page/GJWLP116E2.jpg)

Todo
アプリ ハンズオン
プロジェクト作成
で新規プロジェクトを作成します。
プロジェクト名は何でも大丈夫です。
特になければ hands_on_todo_app でお願いします。
VS Code
pregum
22


# Page. 23

![Page Image](https://bcdn.docswell.com/page/4EZMKPPRJ3.jpg)

Todo
アプリ ハンズオン
サンプル(カウンターアプリ)動作確認
作成したプロジェクトをAndroid エミュレータで動かしてみます。
ここではVS Codeを使用します。
main.dart を VSCode 上で選択後、起動先エミュレータを設定します。
その後、F5で無事起動すればOK
pregum
23


# Page. 24

![Page Image](https://bcdn.docswell.com/page/Y76NQMM17V.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
TodoTileWidget
クラスの作成
ファイルを作成し、
クラスを作成します。
todo_tile_widget.dart
TodoTileWidget
ファイル内に
class TodoTileWidget extends StatefulWidget {
// :
}
class _TodoTileWidgetState extends State&lt;TodoTileWidget&gt; {
// :
}
pregum
24


# Page. 25

![Page Image](https://bcdn.docswell.com/page/G755RZZL74.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
Hive
プラグインのインポート
pubspec.yaml
dependencies
ファイルの
に下記ライブラリを記載し、保存します。
dependencies:
// :
hive: 2.2.3
uuid: 3.0.6
intl: 0.17.0
hive_flutter: 1.1.0
インデントがずれているとうまく読み込めないのでご注意下さい。
※
pregum
25


# Page. 26

![Page Image](https://bcdn.docswell.com/page/9J2NDRR3ER.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
Hive
の開発関連のプラグインをインポート
ファイルの
に下記ライブラリを記載し、保存します。
pubspec.yaml
dev_dependencies
dev_dependencies:
// :
hive_generator: 1.1.3
build_runner: 2.2.0
※
インデントがずれているとうまく読み込めないのでご注意下さい。
pregum
26


# Page. 27

![Page Image](https://bcdn.docswell.com/page/DEYP2DD8EM.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
ファイルを配置
共有しましたフォルダ内のファイルを
lib フォルダ直下へ配置します。
pregum
27


# Page. 28

![Page Image](https://bcdn.docswell.com/page/VJN5866978.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
引数にTodoクラスのオブジェクトを設定
TodoTileWidget
クラスの引数に MyTodo クラスの引数を追加します。
class TodoTileWidget extends StatefulWidget {
final MyTodo todo;
const TodoTileWidget({ Key? key, required this.todo, })
: super(key: key);
}
class _TodoTileWidgetState extends State&lt;TodoTileWidget&gt; {
//
widget.todo
}
使うときは
pregum
でアクセス可能
28


# Page. 29

![Page Image](https://bcdn.docswell.com/page/YE9YKLL3J3.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
Tile
ウィジェットを作成
の
メソッドに
の順でウィジェットを配置
TodoTileWidget
build
Card &gt; CheckboxListTile &gt; Text
Widget build(BuildContext context) {
return Card(
child: CheckboxListTile(
value: widget.todo.isCompleted, // check
onChanged: (bool? newValue) { }, //
ON/OFF
title: Text( widget.todo.taskName ), //
subtitle: Text(&#039;
: ${ widget.todo.updatedAt }&#039;), //
)
);
pregum
}
更新日
用の変数を設定
チェックの
時のコールバックを設定
タスク名を設定
更新日を設定
29


# Page. 30

![Page Image](https://bcdn.docswell.com/page/GE86RXXL7D.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
未チェック/チェック済 変数の設定
先ほどの CheckboxListTile の onChanged プロパティに
未チェック/チェック済の切り替え時に実行される処理を記述します。
child: CheckboxListTile(
// :
onChanged: (bool? newValue) async {
if (newValue == null) { return; }
widget.todo.isCompleted = newValue; //
await MyTodoManager.instance.updateTodo(widget.todo);
}
// :
)
これだけだと画面に反映されない (・x・)
pregum
30


# Page. 31

![Page Image](https://bcdn.docswell.com/page/LEL9K88QJR.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
完了時に取り消し線をつける処理を追加
の title プロパティ
に取り消し線の処理を追加します。
CheckboxListTile
child: CheckboxListTile(
// :
title: Text( widget.doto.taskName,
style: widget.todo.isCompleted
? const TextStyle(decoration: TextDecoration.lineThrough) //
: null, //
),
// :
)
未完了時は取り消し線無し
pregum
完了時は取り消し線有り
31


# Page. 32

![Page Image](https://bcdn.docswell.com/page/4JMZ26XKEW.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
編集と削除用コールバックを引数に追加
TodoTileWidget
クラスに編集と削除用のコールバックを追加します。
class TodoTileWidget extends StatefulWidget {
final MyTodo todo;
final Function()? onDismiss; //
final Function()? onLongTap; //
const TodoTileWidget({
Key? key,
required this.todo,
this.onDismiss, //
-this.onLongTap, //
-}) : super(key: key);
削除用コールバック -- 追加した行
編集用コールバック -- 追加した行
削除用コールバック
編集用コールバック
pregum
追加した行
追加した行
32


# Page. 33

![Page Image](https://bcdn.docswell.com/page/PJR6MPN679.jpg)

Todo
アプリ ハンズオン
1
つのタスクUI作成
編集と削除用コールバックを引数に追加
の
メソッドに配置した Card ウィジェットを
ウィジェットで包みます。
TodoTileWidget
build
MyTodoTileWrapper
Widget build(BuildContext context) {
return MyTodoTileWrapper(
todo: widget.todo,
onDismiss: () { widget.onDismiss?.call(); },
onLongTap: () { widget.onLongTap?.call(); },
child: Card(
// :
pregum
33


# Page. 34

![Page Image](https://bcdn.docswell.com/page/PEXMV3ND7X.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
todo_page.dart
ファイルの作成
フォルダ直下に todo_page.dart ファイルを作成します。
todo_page.dart ファイル内に TodoPage クラスを作成します。
lib
class TodoPage extends StatefulWidget {
// :
}
class _TodoPageState extends State&lt;TodoPage&gt; {
// :
}
pregum
34


# Page. 35

![Page Image](https://bcdn.docswell.com/page/3EKGQYNDJD.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
MyUtils mixin
_TodoPageState
の追加
クラスに MyUtils mixinを適用します。
class _TodoPageState extends State&lt;TodoPage&gt; with MyUtils {
// :
これで、 showDeletedTodoSnackBar , showEditingTodoDialog などが使え
るようになります。
※ 追加後、 my_utils.dart ファイルインポートを忘れないように
してください。
pregum
35


# Page. 36

![Page Image](https://bcdn.docswell.com/page/L73NP9VP75.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
TodoTileWidget
ウィジェットを配置
先ほど作成した TodoPage クラスの build メソッドに
TodoTileWidget ウィジェットを配置します。
@override
Widget build(BuildContext context) {
final todo = MyTodo(id: &#039;test&#039;, taskName: &#039;
return TodoTileWidget(todo: todo);
}
pregum
タスク1&#039;,
isCompleted: false);
36


# Page. 37

![Page Image](https://bcdn.docswell.com/page/87DWLG83JG.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
TodoTileWidget
TodoTileWidget
のonDissmissとonLongTapの設定
の onDissmiss と onLongTap を記述します。
return TodoTileWidget(
todo: todo,
onDismiss: () async {
await MyTodoManager.instance.deleteTodo(todo);
showDeletedTodoSnackBar(context, todo, index);
},
onLongTap: () async {
await showEditingTodoDialog(context, todo, newItem: false);
},
);
pregum
37


# Page. 38

![Page Image](https://bcdn.docswell.com/page/VJP9238PE8.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
ListView
ウィジェットを追加
先ほど配置した TodoTileWidget を ListView ウィジェットで包みます。
Widget build(BuildContext context) {
final todo = MyTodo(id: &#039;test&#039;, taskName: &#039;
final todos = [todo];
return ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
final todo = todos[index];
return TodoTileWidget(
// :
pregum
タスク1&#039;,
isCompleted: false);
38


# Page. 39

![Page Image](https://bcdn.docswell.com/page/2EVMD4NVEQ.jpg)

Todo
アプリ ハンズオン
リスト形式のUIを作成
MyLoadingTodoWidget
の配置
先ほど配置した ListView を MyLoadingTodoWidget で包みます。
Widget build(BuildContext context) {
return MyLoadingTodoWidget(
builder: ((todos) {
return ListView.builder(
// :
}),
);
ListView
pregum
のreturnと仮で作成していたtodo, todosは削除します。
39


# Page. 40

![Page Image](https://bcdn.docswell.com/page/57GGY1K17L.jpg)

Todo
アプリ ハンズオン
main.dart
hive
への配置
にMyTodoのアダプタクラスを登録
main.dart
ファイルの main メソッド内を下記のように書き換えます。
Future&lt;void&gt; main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(MyTodoAdapter());
}
pregum
runApp(const MyApp());
40


# Page. 41

![Page Image](https://bcdn.docswell.com/page/4EQXMDNN7P.jpg)

Todo
アプリ ハンズオン
main.dart
への配置
_MyHomePageState
_MyHomePageState
す。
にTodoPageを配置
クラスの build メソッド内に TodoPage を配置しま
Widget build(BuildContext context) {
return Scaffold(
// :
body: const TodoPage(),
// :
pregum
41


# Page. 42

![Page Image](https://bcdn.docswell.com/page/KJ46VZG371.jpg)

Todo
アプリ ハンズオン
main.dart
への配置
_MyHomePageState
にFABの処理を設定
を配置したその下の floatingActionButton.onPressd の処理を
書き換えます。
TodoPage
// :
body: const TodoPage(),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await MyTodoManager.instance.createNewTodo();
},
),
// :
pregum
42


# Page. 43

![Page Image](https://bcdn.docswell.com/page/LE1V3RDZ7G.jpg)

Todo
アプリ ハンズオン
完成
お疲れ様でした
pregum
43


# Page. 44

![Page Image](https://bcdn.docswell.com/page/GEWLP1Y672.jpg)

Todo
アプリ ハンズオン
改善ヒント
更新時、特定のtodoタスクのみ更新させる
状態管理ライブラリを使用してコード量を減らす
完了todoタスクを非表示にする機能の追加
todo タスクの順番を入れ替える機能の追加
pregum
44


# Page. 45

![Page Image](https://bcdn.docswell.com/page/47ZMKPXRE3.jpg)

Todo
アプリ ハンズオン
参考サイト
https://twitter.com/gethackteam/status/1268892357027663873?
ref_src=twsrc^tfw|twcamp^tweetembed|twterm^126889235702
7663873|twgr^12007820d2fc3fecbe0ca6381183ab580763b432|
twcon^s1_&amp;ref_url=https%3A%2F%2Fqiita.com%2FHiroyuki_OSA
KI%2Fitems%2Ff3f88ae535550e95389d
https://qiita.com/Hiroyuki_OSAKI/items/f3f88ae535550e95389d
https://ui.dev/imperative-vs-declarative-programming
pregum
45


