🦅
Flutterの画面遷移(Navigator)をエフェクトを使ってかっこよく、コードはスッキリさせたい
発生した問題
- FlutterのNavigatorはデフォルトだと下から上へのスライドしかない(フェードや横のスライドを入れたい)
- Routeの設定をMaterialAppに記載していくと、MaterialAppの中身が肥大化する。
作成したコードのイメージ
main.dart
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('ja', 'JP'),
],
theme: ThemeData(
primarySwatch: Colors.brown,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
// ここに定義することで、
// Navigator.of(context).pushNamed("/aaa");
// で遷移できるが、MaterialAppが長くなることに加えて、
// 下から上への画面遷移になってしまうのが嫌だ。
routes: <String, WidgetBuilder>{
'/aaa': (_) => new AAA(),
'/bbb': (_) => new BBB(),
'/ccc': (_) => new CCC(),
},
home: MyHomePage(title: 'My App'),
);
}
}
環境
- macOS Catalina 10.15.4
- Android Studio 3.6.1
- Flutter 1.17.0
結論
1. FlutterのNavigatorはデフォルトだと下から上へのスライドしかない(フェードや横のスライドを入れたい)
page_transitionを使うことで解決しました。
pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
page_transition: ^1.1.5
$ flutter pub get
main.dart
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('ja', 'JP'),
],
theme: ThemeData(
primarySwatch: Colors.brown,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
// ここ
// Navigator.of(context).pushNamed("/aaa");
// で遷移できることに加えて、遷移のエフェクトを設定できる。
// しかしながら、MaterialAppがさらに長くなってしまった。
onGenerateRoute: (settings) {
switch (settings.name) {
// よく見る右から左へ画面遷移するパターン
case '/aaa':
return PageTransition(
child: AAA(),
type: PageTransitionType.rightToLeft,
settings: settings,
);
break;
// じんわりフェードで画面遷移するパターン
case '/bbb':
return PageTransition(
child: BBB(),
type: PageTransitionType.fade,
settings: settings,
);
break;
// Navigatorのデフォルト遷移パターン
case '/ccc':
return PageTransition(
child: CCC(),
type: PageTransitionType.downToUp,
settings: settings,
);
break;
default:
return null;
}
}
home: MyHomePage(title: 'My App'),
);
}
}
このほかにもエフェクトが使えるので、page_transitionを見てみてください。
2. Routeの設定をMaterialAppに記載していくと、MaterialAppの中身が肥大化する。
他のLaravelやNuxtのようにRouterファイルとして切り出しました。
まずは、router.dart
というファイルでrouteとエフェクトを定義してから、
router.dart
import 'package:flutter/material.dart';
import 'package:page_transition/page_transition.dart';
// 適宜呼びたいページをimportしてください
mixin PageRouter implements StatelessWidget {
static Route generate (RouteSettings settings) {
switch (settings.name) {
// よく見る右から左へ画面遷移するパターン
case '/aaa':
return PageTransition(
child: AAA(),
type: PageTransitionType.rightToLeft,
settings: settings,
);
break;
// じんわりフェードで画面遷移するパターン
case '/bbb':
return PageTransition(
child: BBB(),
type: PageTransitionType.fade,
settings: settings,
);
break;
// Navigatorのデフォルト遷移パターン
case '/ccc':
return PageTransition(
child: CCC(),
type: PageTransitionType.downToUp,
settings: settings,
);
break;
default:
return null;
}
}
}
main.dart
で作成したクラスメソッドを呼び出すだけでOK
main.dart
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('ja', 'JP'),
],
theme: ThemeData(
primarySwatch: Colors.brown,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
// ここで呼び出すだけでOK!
onGenerateRoute: PageRouter.generate
home: MyHomePage(title: 'My App'),
);
}
}
今後、ページの追加があるときにはrouter.dart
を編集すればOKです。
何か修正点やもっといい案があればぜひコメント欄でください!
Discussion