はじめに
前回はFlutter Widget of the Weekの「#133 Shortcuts」、「#134 Actions」、「#135 firebase_ui_auth」を紹介しました。
今回はその続きで「#136 FutureBuilder(Take 2)」、「#137 NavigationBar」、「#138 go_router」の3つです。
前回の記事はこちら
またGitHubにも公開しています。
GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.
Flutter Widget of the Week
環境
- Flutter 3.7.0
記事にした時点でのバージョンです。GitHubに公開しているのは常に最新の安定版(stable)を使う予定です。
#136 FutureBuilder(Take 2)
FutureBuilderとは
#6 FutureBuilderと同じです。なぜTake 2が必要なのかは不明です。
サンプルコード
import 'package:flutter/material.dart';
class SamplePage136 extends StatefulWidget {
const SamplePage136({
super.key,
});
@override
SamplePage136State createState() => SamplePage136State();
}
class SamplePage136State extends State<SamplePage136> {
late Future<String> _success;
late Future<String> _failure;
@override
void initState() {
super.initState();
_success = _successFuture();
_failure = _failureFuture();
}
Future<String> _successFuture() async {
await Future.delayed(const Duration(seconds: 2), () {});
return 'Success!!';
}
Future<String> _failureFuture() async {
await Future.delayed(const Duration(seconds: 2), () {});
try {
throw Exception('Error');
} on Exception catch (e) {
return Future.error(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('FutureBuilder(Take 2)'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('FutureBuilder Success'),
FutureBuilder(
future: _success,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.info,
color: Colors.red,
),
Text(snapshot.error?.toString() ?? ''),
],
);
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.check_circle,
color: Colors.green,
),
Text(snapshot.data?.toString() ?? ''),
],
);
} else {
return const CircularProgressIndicator();
}
},
),
const SizedBox(height: 20),
const Text('FutureBuilder Error'),
FutureBuilder(
future: _failure,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.info,
color: Colors.red,
),
Text(snapshot.error?.toString() ?? ''),
],
);
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.check_circle,
color: Colors.green,
),
Text(snapshot.data?.toString() ?? ''),
],
);
} else {
return const CircularProgressIndicator();
}
},
),
],
),
),
),
);
}
}
結果
動画
公式リファレンス
FutureBuilder class - widgets library - Dart API
API docs for the FutureBuilder class from the widgets library, for the Dart programming language.
#137 NavigationBar
NavigationBarとは
機能としてはBottomNavigationBarと全く同じですが、
BottomNavigationBarはMaterial 2、NavigationBarはMaterial 3のデザインに準拠している違いがあります。
サンプルコード
import 'package:flutter/material.dart';
class SamplePage137 extends StatefulWidget {
const SamplePage137({
super.key,
});
@override
SamplePage137State createState() => SamplePage137State();
}
class SamplePage137State extends State<SamplePage137> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('NavigationBar'),
),
bottomNavigationBar: NavigationBar(
selectedIndex: _selectedIndex,
destinations: const [
NavigationDestination(
icon: Icon(Icons.home),
label: 'Home',
),
NavigationDestination(
icon: Icon(Icons.explore),
label: 'Explore',
),
NavigationDestination(
icon: Icon(Icons.person),
label: 'Profile',
),
NavigationDestination(
icon: Icon(Icons.settings),
label: 'Settings',
),
],
onDestinationSelected: (value) {
setState(() {
_selectedIndex = value;
});
},
),
);
}
}
結果
動画
公式リファレンス
NavigationBar class - material library - Dart API
API docs for the NavigationBar class from the material library, for the Dart programming language.
#138 go_router
go_routerとは
FlutterのNavigation2.0の実装が簡単になるパッケージです。
最初は有志のパッケージでしたが公式のパッケージになりました。
サンプルコード
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class SamplePage138 extends StatefulWidget {
const SamplePage138({
super.key,
});
@override
SamplePage138State createState() => SamplePage138State();
}
class SamplePage138State extends State<SamplePage138> {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: router,
);
}
final router = GoRouter(
initialLocation: '/main',
routes: [
GoRoute(
path: '/main',
builder: (context, state) => const SamplePage138Main(),
routes: [
GoRoute(
path: 'sub1',
builder: (context, state) => const SamplePage138Sub1(),
),
GoRoute(
path: 'sub2',
builder: (context, state) => const SamplePage138Sub2(),
routes: [
GoRoute(
path: 'sub3',
builder: (context, state) => const SamplePage138Sub3(),
),
],
),
],
),
],
);
}
class SamplePage138Main extends StatelessWidget {
const SamplePage138Main({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('go_router'),
),
body: SafeArea(
child: ListView(
children: [
ListTile(
title: const Text('Sub1'),
trailing: const Icon(Icons.navigate_next),
onTap: () {
context.go('/main/sub1');
},
),
ListTile(
title: const Text('Sub2'),
trailing: const Icon(Icons.navigate_next),
onTap: () {
context.go('/main/sub2');
},
),
],
),
),
);
}
}
class SamplePage138Sub1 extends StatelessWidget {
const SamplePage138Sub1({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sub1'),
),
);
}
}
class SamplePage138Sub2 extends StatelessWidget {
const SamplePage138Sub2({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sub2'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.go('/main/sub2/sub3');
},
child: const Icon(Icons.navigate_next),
),
);
}
}
class SamplePage138Sub3 extends StatelessWidget {
const SamplePage138Sub3({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sub3'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.go('/main');
},
child: const Icon(Icons.home),
),
);
}
}
結果
動画
公式リファレンス
go_router | Flutter package
A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more
さいごに
Flutter Widget of the WeekはPackage of the Weekしかやらないのだろうか?
おすすめ参考書
リンク
GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.
コメント