LoginSignup
103
66

More than 3 years have passed since last update.

Flutterで画面の遷移のタイミングで処理を行う

Last updated at Posted at 2017-08-03

[2019/05/13 追記] Issue#29596 は プルリク 30422 で修正されました。 [2019/04/01 追記] #29596 によると、iOSでスワイプで戻ると didPop, didPopNext が呼ばれないようです。


FlutterのWidgetには、画面の遷移に関するイベントを処理するためのハンドラ(メソッド)がありません。これは当然で、Widgetは部品であるため、画面の一部なのか全体なのか、使う側次第だからです。

さて、Flutterにおいて画面遷移に関する処理を行っているのはNavigatorというクラスです。このクラスに対してpushやpopという操作を行います。このNavigatorに対してはNavigatorObserverのリストを渡すことができます。これにより画面遷移に関するイベントを受け取ることができます。

NavigatorObserverを実装したクラスを自分で実装して処理してもよいのですが、それをStateで処理することが目的であれば、RouteObserverというものを使うと便利です。

以下のようにMaterialAppやWidgetsAppにオブザーバーを設定しておきます。

final RouteObserver<PageRoute> routeObserver = new RouteObserver<PageRoute>();
Widget build(BuildContext context) {
  ...
  return new MaterialApp(
    ...
    navigatorObservers: <NavigatorObserver>[routeObserver],
    ...
  );
}

続いて、StateにRouteAwareをmixinして、routeObserverに対してsubscribe/unsubscribeします。

class YourPageWidgetState extends State<YourPageWidget> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  // 上の画面がpopされて、この画面に戻ったときに呼ばれます
  void didPopNext() {
    debugPrint("didPopNext ${runtimeType}");
  }

  // この画面がpushされたときに呼ばれます
  void didPush() {
    debugPrint("didPush ${runtimeType}");
  }

  // この画面がpopされたときに呼ばれます
  void didPop() {
    debugPrint("didPop ${runtimeType}");
  }

  // この画面から新しい画面をpushしたときに呼ばれます
  void didPushNext() {
    debugPrint("didPushNext ${runtimeType}");
  }
}

新しい画面が呼ばれるときに:

  • 呼び出し元で didPushNext
  • 呼び出し先で disPush

画面を戻るときに:

  • 戻る元で disPop
  • 戻る先で disPopNext

が呼ばれます。

どの画面でも共通の処理があるのであれば、基底クラスとしてRouteAwareStateのようなものを作り、各画面のStateはそれをextendsするようにするとよさそうです。

103
66
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
103
66