【 Flutter 】Flutter を 基礎 から 学習 ( スタートガイド編 ) part23 画面遷移 その他の遷移方法

基礎 から 学ぶ Flutter 」という書籍で  学習 したことを ブログでアウトプットしていこうと思います。今回は スタートガイド編 ( part23 )です。

前回

【 Flutter 】Flutter を 基礎 から 学習 ( スタートガイド編 ) part22 画面遷移 Named Routes

今回はNavigatorクラスのそのほかの画面遷移について学習します。

画面遷移

maybePop

ルートのスタックが残り1つになるまでpopします。
「最初の画面に戻る」の場合に使用する想定でしょうかね?

最初の画面→2画面目→3画面目 の構成で、3画面目でmaybePopを使用してみました。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override

Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',

theme: ThemeData(
        primarySwatch: Colors.blue,

),

// home: MyHomePage(title: 'Flutter Demo Home Page'),

initialRoute: '/',

routes: {
        '/': (context) => FirstPage(),

'/second': (context) => SecondPage(),

'/third': (context) => ThirdPage(),

},

);

}
}

class FirstPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');

},

child: Text('Next Page'),

),

),

);

}
}

class SecondPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/third');

},

child: Text('Next Page'),

),

),

);

}
}

class ThirdPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Third Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.maybePop(context); // ★ここに注目

},

child: Text('Go back'),

),

),

);

}
}
 

実行してみました。


最初の画面画面に戻ると思ったのですがそうではなかったですね・・・なんでしょうこれは・・・。

canPop

popできるかどうか確認するためのメソッドのようです。

popできない(つまりルート画面)の場合はfalseとなります。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override

Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',

theme: ThemeData(
        primarySwatch: Colors.blue,

),

// home: MyHomePage(title: 'Flutter Demo Home Page'),

initialRoute: '/',

routes: {
        '/': (context) => FirstPage(),

'/second': (context) => SecondPage(),

'/third': (context) => ThirdPage(),

},

);

}
}

class FirstPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            print('最初の画面でcanPop = ' + Navigator.canPop(context).toString());

Navigator.pushNamed(context, '/second');

},

child: Text('Next Page'),

),

),

);

}
}

class SecondPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            print('2画面目でcanPop = ' + Navigator.canPop(context).toString());

Navigator.pushNamed(context, '/third');

},

child: Text('Next Page'),

),

),

);

}
}

class ThirdPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Third Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            print('3画面目でcanPop = ' + Navigator.canPop(context).toString());

Navigator.maybePop(context);

},

child: Text('Go back'),

),

),

);

}
}
 

実行して確認しました。

想定通りですね。

pushReplacement, pushReplacementNamed

First -> Second(ここでpushReplacement) -> Third の順で画面遷移した場合、
Thrird画面でpopするとFirst画面に遷移するということのようです。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override

Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',

theme: ThemeData(
        primarySwatch: Colors.blue,

),

// home: MyHomePage(title: 'Flutter Demo Home Page'),

initialRoute: '/',

routes: {
        '/': (context) => FirstPage(),

'/second': (context) => SecondPage(),

'/third': (context) => ThirdPage(),

},

);

}
}

class FirstPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');

},

child: Text('Next Page'),

),

),

);

}
}

class SecondPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushReplacementNamed(context, '/third'); // ★ここに注目

},

child: Text('Next Page'),

),

),

);

}
}

class ThirdPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Third Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);

},

child: Text('Go back'),

),

),

);

}
}
 

実行してみると確かにThirdからいきなりFirstの画面に戻っているのがわかります。

popAndPushNamed

popAndPushメソッドは無いのですね。

このメソッドが実装された画面Widget(ルート)を削除し、指定された画面Widgetをスタックの最後に挿入する。という認識でよいでしょうかね。

First -> Second-> Third(ここでpopAndPushNamed)
とすると、スタックはFirst -> Second-> (Third消滅)First
となります。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override

Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',

theme: ThemeData(
        primarySwatch: Colors.blue,

),

// home: MyHomePage(title: 'Flutter Demo Home Page'),

initialRoute: '/',

routes: {
        '/': (context) => FirstPage(),

'/second': (context) => SecondPage(),

'/third': (context) => ThirdPage(),

},

);

}
}

class FirstPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');

},

child: Text('Next Page'),

),

),

);

}
}

class SecondPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/third');

},

child: Text('Next Page'),

),

),

);

}
}

class ThirdPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Third Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.popAndPushNamed(context, '/'); // ここに注目

},

child: Text('Go back'),

),

),

);

}
}
 

実行してみたところFirst(1回目) -> Second -> Third -> First(2回目)の順で画面が表示されました。

注目したいのはFirst画面に「戻る」アイコンが表示されていることです。
スタックされたFirst画面が表示されていることがわかります。
次にこのFirst画面の「戻る」アイコンをクリックするとSecond画面が表示されました。
Third画面がスタック上からなくなっているということですね。

最後に

文章にすると複雑(というか私の文章能力が無い)ですが動きを見ると感覚的に分かりますね。

今日はここまで!