【Flutter入門】画面の戻るボタンが押された際に値を返す方法を解説するよ

本記事は、マルチプラットフォーム開発のSDK【Flutter】を用いたモバイルアプリ開発入門の為の記事です。

ダーフク

Flutterでは、各画面の左上に戻るボタンが標準実装されています。今回はこの戻るボタンを押した際に値を返す方法を解説します。

やりたいこと

Flutterでは、アプリの雛形を作成する際に Scaffold Widgetを用います。

このWidgetにはappBarプロパティがあり、これによりアプリのヘッダーを簡単に実装することができます。

そしてある画面から次の画面へ遷移した際、次画面のヘッダーの左端に自動で戻るアイコンが表示されます。

今回は、この戻るボタンが押された際にどのように返り値を取得するのかについて解説します。

方法

  • 遷移元画面では、Navigator.pushをして返り値をawaitで待つ
  • 遷移先画面では、ScaffoldをWillPopScopeで囲み、手動でpopするようにする

コード解説

遷移元画面

まず遷移元では、ボタンが押されたときに次の画面をpushします。

そして、awaitを用いて返り値を待ちます。

onPressed: () async {
                bool result = await Navigator.of(context).push(
                  MaterialPageRoute<bool>(
                    builder: (context) => NextPage(),
                  ),
                );
              },

 

遷移先画面

ScaffoldをWillPopScopeで囲みます。

WillPopScopeのonWillPopメソッドで、手動でNavigator.pop(false)をする必要があります。

また、遷移元ではawaitしているため、Future.value(false)をreturnする必要があります。

補足

Future.value(true)を返してしまうと、pop関数が2度実行され、遷移元の画面もpopされてしまいます。

return WillPopScope(
      onWillPop: () {
        Navigator.of(context).pop(返したい値);
        return Future.value(false);
      },
      child: Scaffold()

 

サンプルアプリ

サンプルアプリでは

  1. 自前で実装した戻るボタン
  2. 自動で実装される戻るアイコン

の2種類で値を返す方法を実装してみました。

戻るアイコンの押下を検知する

サンプルアプリのソースコード

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'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _result = "初期表示";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text("次の画面へ"),
              onPressed: () async {
                String result = await Navigator.of(context).push(
                  MaterialPageRoute<String>(
                    builder: (context) => NextPage(),
                  ),
                );
                setState(() => _result = result);
              },
            ),
            Text(_result)
          ],
        ),
      ),
    );
  }
}

class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        Navigator.of(context).pop("戻るアイコンからの遷移");
        return Future.value(false);
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text("NextPage"),
        ),
        body: Center(
          child: RaisedButton(
            child: Text("戻る"),
            onPressed: () => Navigator.of(context).pop("戻るボタンからの遷移"),
          ),
        ),
      ),
    );
  }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です