🟤

Flutter 戻るボタン(OSのバックボタン)を気にする

2024/06/19に公開

デバイスの戻るボタン

Androidには、ハードウェアボタンやソフトナビゲーションバー、ジェスチャーバックを使うことで、アプリ内に配置された戻る機能(Navigator.pop())を持ったUIボタン等をタップせずに現在のアクティビティ(画面)を終了し前のアクティビティに戻ることができる。(以下OSバックと呼ぶ)
※iOSはジェスチャーのみ

実装時の注意

アプリを開発するときは、このOSバックを考慮したナビゲーション設計をしておくべきで、たとえばアプリ内のUIとしては現在の画面から前の画面に戻れる操作は行えなくても、ユーザーはこのOSバックを使うことで戻れてしまう。
具体的には、以下のような画面遷移をする新規ユーザー登録フローがあったとき

①TOP画面 → ②メール&パスワード入力画面 → ③認証コード入力画面 → ④登録完了画面

①〜③までは、UIにもアプリバーなどに戻るボタンがあり、1つ前の画面に戻れることが望ましいが、④の画面まで至った場合は、③の画面に戻れてほしくないようなケースがある。
このとき、④の画面にはアプリバーなどに戻るボタンがなくてもOSバック操作で戻れてしまうのが注意点となる。

対応

対応は主に2つある。

  • 特定の画面でOSバックを無効にする
  • ナビゲーション設計を考慮する

特定の画面でOSバックを無効にする(PopScopeウィジェットを使う)

Flutterには、PopScopeというウィジェットがあり、プロパティをcanPop: falseとすればOSバックを無効化できる。

PopScope(
    canPop: false,
    child: Scaffold(
        body: ...
    )
)

ただし、アプリのUXとしてOSバックが無効なことは、ユーザーに混乱を与えかねないので使用には十分な考慮がなされるべきである。(ダイアログで無効であることを知らせる etc.)

ちなみに、PopScopeはOSバックを無効にするためのウィジェットというよりは、Android 14から導入された Predictive Back Gesture (予測型「戻る」ジェスチャー)に対応するためのウィジェットなので、以下のようにonPopInvokedというプロパティに、画面が戻ろうとしている時の動作をコールバックで指定しておくことができる。これを使って、画面が戻る前に確認ダイアログを出すといったことが可能になる。

PopScope(
    canPop: false,
    onPopInvoked: (didPop) async {
        ...
        // 確認ダイアログ表示処理
        ...
    },
    child: Scaffold(
        body: ...
    )
)

ナビゲーション設計を考慮する

これはとてもシンプルだが強力な対応で、先ほどの例の③から④への画面遷移時に、それまでスタックしていた②と③のナビゲーションを破棄して①の上に④の画面が来るようにしてあげることが有効。

Navigator.of(context).pushNamedAndRemoveUntil(
    Routes.tourokuKanryou,
    ModalRoute.withName(Routes.topGamen),
);

Discussion