■ルーティング
画面遷移を一元管理するための仕組み。
(ユーザーの操作に対してどの画面を表示するかを管理する仕組み)
- Navigator1.0: Navigator.push/popをするだけ。コードが複雑化
- Navigator2.0: pages[], onPopPageなどを使う。ページの状態を一元的に管理し、状態に応じて遷移を制御
- go_router: Navigator2.0をラップして使いやすくしたもの。GoRoute(),routes[],redirectなど。googleも推奨している
■導入手順
pubspec.yamlのdependenciesにgo_routerを追加し、Pub getボタンを押す
(or ターミナルから「flutter pub add go_router」と打つと自動でpubspec.yamlに追記される)
サンプルコード
dart main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
bool isFirstPage = false;
final _router = GoRouter(routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/details1',
builder: (context, state) => const DetailsScreen(title: '詳細ページ1'),
),
// GoRoute(
// path: '/details2',
// builder: (context, state) => const DetailsScreen(title: '詳細ページ2'),
// ),
GoRoute(
path: '/details2',
//----------------------------------------------------------
// スライドトランジションのカスタム (下から上)
pageBuilder: (BuildContext context, GoRouterState state) {
return CustomTransitionPage<void>(
child: const DetailsScreen(title: '詳細ページ2'),
transitionDuration: const Duration(milliseconds: 500),
transitionsBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return SlideTransition(
//スライドトランジション (下から上へのスライド)
position: Tween<Offset>(
// begin: const Offset(1.0, 0.0),//右からから左
begin: const Offset(0.0, 1.0), //下から上
end: Offset.zero,
).animate(animation),
child: child,
);
},
);
},
//----------------------------------------------------------
),
// /detailsでアクセスされたら、isFirstPageの値によって/details1か/details2にリダイレクト
GoRoute(
path: '/details',
redirect: (BuildContext context, GoRouterState state) {
if (isFirstPage) {
return '/details1';
} else {
return '/details2';
}
},
),
]);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ホーム画面')),
body: Center(
child: ElevatedButton(
// デフォルト
// onPressed: () => context.go('/details'),
// プッシュ遷移
onPressed: () => context.push('/details'),
child: const Text('詳細画面へ移る'),
),
),
);
}
}
class DetailsScreen extends StatelessWidget {
const DetailsScreen({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
// child: ElevatedButton(onPressed: () => context.go('/'),
child: ElevatedButton(
onPressed: () => context.pop(),
child: const Text('ホーム画面へ移る'),
),
),
);
}
}