続いて読んでいく
これはFlutter SamplesのTesting_appを読むだけの記事の続きです。
part4はmain.dartだけでしたが他のdartファイルも読んでみます
home.dart
home.dartはアプリを実行したときに表示された一番初めの画面を作っているところです。
// Copyright 2020 The Flutter team. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:testing_app/models/favorites.dart'; import 'package:testing_app/screens/favorites.dart'; //パッケージを読み込みます class HomePage extends StatelessWidget { static const routeName = '/'; const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( //上にある青い部分を作ります title: const Text('Testing Sample'), //Appbarに置くタイトル文字を入れてます actions: [ TextButton.icon( style: TextButton.styleFrom(backgroundColor: Colors.white), onPressed: () { Navigator.pushNamed(context, FavoritesPage.routeName); }, icon: const Icon(Icons.favorite_border), label: const Text('Favorites'), ), //ここでボタンを作っています。これをコピペして二つにすればボタン二つできます //Appbar内にあるのでTesting Sampleと書かれたAppBarにこのボタンが配置されます。
//ListViewウィジェットはitemを0~99までスクロールで見れるようにしているところです //https://flutter.ctrnost.com/basic/layout/listview/ body: ListView.builder( itemCount: 100, //itemは百個ある cacheExtent: 20.0, //スクロールの前に要素をキャッシュしておく //例えば画像とかでスクロールごとにリロードされないようにしたりできる //https://selegee.com/7545/ controller: ScrollController(), //スクロールするところ padding: const EdgeInsets.symmetric(vertical: 16), //垂直に余白を作ってる //https://ttydev.com/post/flutter/edge-insets itemBuilder: (context, index) => ItemTile(index), //アロー文です ItemTileが戻り値になる //https://www.choge-blog.com/programming/dart-arrow/ ), //さきほどの戻り値ItemTileをここで記述 class ItemTile extends StatelessWidget { final int itemNo; const ItemTile(this.itemNo, {super.key}); @override //いつもの Widget build(BuildContext context) { final favoritesList = context.watch<Favorites>(); //ここでfavoritesListに入ったものをmodels/favorites.dartのFavoritesに渡しています。 //’親Widgetで Provider<T>.value() を使い データを渡す’ //’子Widgetで context.watch<T>() を使い データを受け取る’ //https://www.flutter-study.dev/create-app/provider より引用 return Padding( padding: const EdgeInsets.all(8.0), //余白を作っている(試しに0とかにしてみるといいかも) child: ListTile( leading: CircleAvatar( backgroundColor: Colors.primaries[itemNo % Colors.primaries.length], ), //円型のアイコンを作る title: Text( 'Item $itemNo', key: Key('text_$itemNo'), ), //アイコンの右のテキスト trailing: IconButton( key: Key('icon_$itemNo'), icon: favoritesList.items.contains(itemNo) ? const Icon(Icons.favorite) : const Icon(Icons.favorite_border), //favoriteボタン(ハート)の追加 //※どちらかをIcons.visibilityにしてみたりしてみよう onPressed: () { !favoritesList.items.contains(itemNo) ? favoritesList.add(itemNo) : favoritesList.remove(itemNo); //押されたときにそのitemnoをfavoriteslistに入れる ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(favoritesList.items.contains(itemNo) ? 'Added to favorites.' : 'Removed from favorites.'), duration: const Duration(seconds: 1), //一番下にメッセージが表示されるSnackBarの設定
home.dartは大きく分けてHomePageという土台とItemTileというItem0から99まであるリストの部分の二つで出来てます
続いてfavorites.dartを見てみましょう。
これはhome.dartのfavoritesボタンを押すと表示されるところですね
// Copyright 2020 The Flutter team. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:testing_app/models/favorites.dart'; //パッケージ読み込み class FavoritesPage extends StatelessWidget { static const routeName = '/favorites_page'; const FavoritesPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Favorites'), ), body: Consumer<Favorites>( builder: (context, value, child) => value.items.isNotEmpty ? ListView.builder( itemCount: value.items.length, padding: const EdgeInsets.symmetric(vertical: 16), itemBuilder: (context, index) => FavoriteItemTile(value.items[index]), ) : const Center( child: Text('No favorites added.'), ), ), ); } } //ここまではhome.dartやmain.dartのscaffoldと同じ土台の部分 class FavoriteItemTile extends StatelessWidget { final int itemNo; const FavoriteItemTile(this.itemNo, {super.key}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: ListTile( leading: CircleAvatar( backgroundColor: Colors.primaries[itemNo % Colors.primaries.length], ), //円形のアイコン作成 //※backgroundcolorの後ろにchild: Text:('test'),と入力してみよう title: Text( 'Item $itemNo', key: Key('favorites_text_$itemNo'), ), //ここはテキスト trailing: IconButton( key: Key('remove_icon_$itemNo'), icon: const Icon(Icons.close), onPressed: () { context.read<Favorites>().remove(itemNo); //Icons.close(×ボタン)を押したらFavoritesリストから削除 ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Removed from favorites.'), duration: Duration(seconds: 1), //SnackBarの設定 ), ); }, ), ), ); } }
もうfavorites.dartはだいたいわかるようになってきましたね
ウィジェットを組み合わせるだけでアプリが出来ていく感じですね
最後にmodelsのfavorites.dartを見てみましょう
// Copyright 2020 The Flutter team. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; /// The [Favorites] class holds a list of favorite items saved by the user. class Favorites extends ChangeNotifier { final List<int> _favoriteItems = []; //List型は同じ型を複数格納するもの //配列みたいなもの //favoriteitemsをList型にした List<int> get items => _favoriteItems; void add(int itemNo) { _favoriteItems.add(itemNo); notifyListeners(); } //Addが呼び出された場合 //itemNoを格納してnotifyListenerを呼び出す void remove(int itemNo) { _favoriteItems.remove(itemNo); notifyListeners(); } //removeが呼び出された場合 //itemNoを削除してnotifyListenerを呼び出す } home.dartに書かれていたfavoritesListに入ったデータはcontext.watchでfavoritesクラスに渡されるのでここが動作します。 favoritesList.addでaddが呼び出され、favoritesList.removeでremoveが呼び出される感じですね
とりあえずこんな感じでだいたい動きがわかってきたかなーと思うので
物は試しということで早速次のパートでアプリを作ってみましょう