くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Flutterで画面遷移するときのいろいろ(Navigator / PageRouteBuilder)

FlutterでWebアプリを作ってみたときに調べたときの備忘録。
画面遷移まわりをまとめてみた。

複数画面をルーティングする

ルーティングは、こんな感じででAppに設定する。

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      // デフォルトのルーティング
      initialRoute: '/',
      // ルーティングの一覧を設定
      routes: {
        '/': (context) => TopPage(title: "TopPage"),
        '/second': (context) => SecondPage(title: "SecondPage"),
      },
    );
  }
}

Navigator.pushNamedを使うと、パスで遷移できる

// Within the `FirstScreen` widget
onPressed: () {
  // Navigate to the second screen using a named route.
  Navigator.pushNamed(context, '/second');
}

戻るときは、popでできる。

// Within the SecondScreen widget
onPressed: () {
  // Navigate back to the first screen by popping the current route off the stack.
  Navigator.pop(context);
}

named routeでパラメタを渡す

オブジェクトで渡すことができるよう。
まずは、引数のクラスを作成。

class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

引数を受け取るクラスはこんな感じ。
ModalRoute.of(context).settings.arguments;で取得する。

class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    // 引数の受け取り
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

    return Scaffold(/* 略 */);
  }
}

引数ありで画面を呼び出すのはこんな感じ。

onPressed: () {                                               
  // argumentsに渡したい引数オブジェクトを設定する      
  Navigator.pushNamed(                                        
    context,                                                  
    ExtractArgumentsScreen.routeName,                         
    arguments: ScreenArguments(                               
      'Extract Arguments Screen',                              
      'This message is extracted in the build method.',       
    ),                                                                                                                 
  );                                                          
},

画面遷移の操作いろいろ

画面遷移のヒストリを操作する処理はいろいろある。

  • 進む(push)
    • push / pushNamed ... 進む
  • 戻る(pop)
    • pop ... 戻る
    • popUntil .. 指定Routeまで戻る
  • 組み合わせ
    • popAndPushNamed ... popしてpushする
  • 置き換え系(replace)
    • replace ... 指定したRouteを置き換え
    • replaceRouteBelow .. 指定したRouteの一つ前を置き換え
    • pushReplacement / pushReplacementNamed ... 現在のRouteを置き換え
  • 削除系(remove)
    • removeRoute ... 指定したRouteを削除
    • removeRouteBelow ... 指定したRouteの一つ前を削除
    • pushAndRemoveUntil / pushNamedAndRemoveUntil ... pushしつつ、指定条件を満たすRouteを削除

一気に戻ったり、置き換えたりするときに使うことがある。

画面遷移時のアニメーション

画面遷移するときは、こんな感じだけど、

Navigator.pushNamed(
  context, 
  '/second', 
  arguments=ScreenArguments("title", "message"),
);

MaterialAppを使ってる場合はMaterialPageRouteを使ってこんな感じになってる。

Navigator.push(
  context,
  MaterialPageRoute(
    settings: RouteSettings(
      name: '/second',
      arguments: ScreenArguments("title", "message"),
    ),
    builder: (context) => SecondPage(),
  ),
);

画面遷移だけ、iOSっぽくしたい場合は、CupertinoPageRouteに変えればOK

Navigator.push(
  context,
  CupertinoPageRoute(
    settings: RouteSettings(
      name: '/second',
      arguments: ScreenArguments("title", "message"),
    ),
    builder: (context) => SecondPage(),
  ),
);

このPageRouteをカスタマイズすれば、画面遷移のアニメーションを変えられる。
PageRouteBuilderを継承すると作成できるらしい。

この記事で紹介されているスライドで遷移する例はこんな感じ。

class SlidePageRoute extends PageRouteBuilder {
  final Widget page;
  final RouteSettings settings;
  SlidePageRoute({this.page, this.settings})
      : super(
    pageBuilder: (
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
        ) {
      return page;
    },
    transitionsBuilder: (
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
        Widget page,
        ) {
      return SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(1, 0),
          end: Offset.zero,
        ).animate(animation),
        child: page,
      );
    },
  );
}

呼び出すときはこんな感じに。builderからpageに変わるので注意。

Navigator.push(
  context,
  SlidePageRoute(
    page: SecondPage()
    settings: RouteSettings(
      name: '/second',
      arguments: ScreenArguments("title", "message"),
    ),
  ),
);

以下のサイトにいろんなアニメーション/トランジションの例があるので、
参考にPageRouteBuilderを作っていけば、いろいろできる。

以上!!

参考にしたサイト様