Help us understand the problem. What is going on with this article?

Flutterの画面遷移(Navigator)をエフェクトを使ってかっこよく、コードはスッキリさせたい

発生した問題

  1. FlutterのNavigatorはデフォルトだと下から上へのスライドしかない(フェードや横のスライドを入れたい)
  2. Routeの設定をMaterialAppに記載していくと、MaterialAppの中身が肥大化する。

作成したコードのイメージ

main.dart
class MyApp extends StatelessWidget {
  @override
  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 {
  @override
  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 {
  @override
  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です。
何か修正点やもっといい案があればぜひコメント欄でください!

qst_exe
鹿児島でフルリモートのフリーランスエンジニアをしながら、YouTuberとしてプログラミングネタの発信、チームヒラマサでのプログラミング教育にも取り組んでいます。
https://bit.ly/2MegXIr
hiramasa-circle
共同開発のエンジニアコミュニティ
https://kusutan.com/hiramasa/344/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした