viewを担当するフォルダを作る
UI(見た目)を記述していくdartファイルを作ります。
それでは、プロジェクトのlibディレクトリ直下にviewというディレクトリを作成し、以下のようなDartファイルを作成します。
(フォルダ名/はフォルダを表し、ファイル名.dartはdartファイルを表しています)
- view/
- root.dart
- todo/
- todo_view.dart
- timeline/
- timeline_view.dart
- settings/
- settings_view.dart
- notify/
- notify_setting_view.dart
それぞれのdartファイルの役割は下記の通りです
- root.dart
- todo,timeline,settingsの内、どれを表示するのかを制御します。
- todo.dart
- 登録されたtodoをすべて表示します。また、todoの登録、変更、削除もここで行います。
- timeline.dart
- 登録されたtodoの内、締め切りが今日であるものをtimeline形式で表示します。
- settings.dart
- 設定の一覧を表示します。今回は通知の設定画面しか作りませんが...
- notify_setting.dart
- 何時間前に通知するのかを設定する画面を表示します。
root.dartに記述する
root.dartに下記の通りに記述してください。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class Root extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
List<String> keys = ["Home", "TimeLine", "Settings"];
List<Icon> icons = [
Icon(Icons.home),
Icon(Icons.timeline),
Icon(Icons.settings),
];
final page_state = useState(0);
List<BottomNavigationBarItem> navi_items = [];
for (int i = 0; i < keys.length; i++) {
navi_items.add(BottomNavigationBarItem(
icon: icons[i],
label: keys[i],
));
}
return Scaffold(
appBar: AppBar(
title: Text(keys[page_state.value]),
),
body: Center(
child: Text(page_state.value.toString()),
),
bottomNavigationBar: BottomNavigationBar(
items: navi_items,
currentIndex: page_state.value,
onTap: (index) {
page_state.value = index;
},
),
);
}
}
次にmain.dartを書き換えます。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:(アプリ名)/view/root.dart';
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Root(),
);
}
}
main.dartではProviderScopeでMyAppが囲まれ、MyAppはHookConsumerWidgetが継承されているのがわかります。これはProviderを使う上で大事なことなので忘れないようにしましょう。
とりあえずはこれで一度実行してみます。
どうでしょうか? 下のナビゲーションバーのアイテムをタッチするたびに画面に表示されている値が変わるのがわかると思います。
root.dartではこの値に合わせて表示する画面を制御していきます。
root.dartの役割がわかったとことで、実際には何が行われているのか解説していこうと思います。
useStateとは?HookConsumerWidgetとは?
HookConsumerWidgetとはStatefulWidgetの変わりに使われるクラスです。このクラスを継承することによってhookとproviderを使うことができるようになります。
root.dartには以下のような変数が存在します。
final page_state = useState(0);
このuseStateとはFlutter Hooksのフックの一つになります。
page_stateのvalueが変更されるたびに更新通知をだし、再描画をしてくれます。
bottomNavigationBarの使い方。
bottomNavigationBarとは文字通り、下に表示されるナビゲーションバーのことです。
このウィジェットをどのように使うのかを解説していこうと思います。
初めに、bottomNavigationBarを構築する要素をまとめた変数は以下になります。
List<BottomNavigationBarItem> navi_items = [];
List<String> keys = ["Home", "TimeLine", "Settings"];
List<Icon> icons = [
Icon(Icons.home),
Icon(Icons.timeline),
Icon(Icons.settings),
];
navi_itemsはBottomNavigationBarに表示されるアイテム(BottomNavigationBarItem)のリストになります。
keysではappbarに表示する文字列とBottomNavigationBarItemのラベルを代入しています。
iconsではBottomNavigationBarItemで使われるアイコンを代入しています。
これだけではnavi_itemsは空のリストなのでこのようにfor文を回すことでnavi_itemsにアイテムを追加していきます。
for (int i = 0; i < keys.length; i++) {
navi_items.add(BottomNavigationBarItem(
icon: icons[i],
label: keys[i],
));
}
これでnavi_itemsがからのリストではなく、BottomNavigationBarItemを格納したリストなのだ、ということが理解できたと思います。
Scaffold(
appBar: AppBar(
title: Text(keys[page_state.value]),
),
body: Center(
child: Text(page_state.value.toString()),
),
bottomNavigationBar: BottomNavigationBar(
items: navi_items,
currentIndex: page_state.value,
onTap: (index) {
page_state.value = index;
},
),
);
最終的にはこのようにBottomNavigationBarはScaffold内に記述され、currentIndexの値に対応するアイテムを色付けなどをして強調表示してくれるようになります。
また、onTapではアイテムがタップされた際の処理を記述します。indexにはタップされたアイテムの要素番号が代入されます。今回の処理ではpage_state.valueにindexが代入され、それに合わせてAppBarのタイトルやbodyのTextで表示される内容が変わることがわかると思います。
まとめ
このようにroot.dartではBottomNavigationBarによってpage_stateの値が変更され画面が再描画されていたということがわかったと思います。
最終的にはpage_stateの値によってtodo,timeline,settingsの内どれを表示するのかを管理することになります。
そのためにも、次の章ではtodo_view.dartを作っていきます。