0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jetpack ComposeでBottomSheet 内の NavHost でバックジェスチャーが効かない問題

0
Posted at

はじめに

ModalBottomSheet の中に NavHost を置いてマルチ画面の構成にしている場合、Android 16+(targetSdk 36)の端末でバックジェスチャーを行うと、NavHost が1画面戻るのではなくシート全体が閉じてしまうというバグが発生しました。

原因

先に原因を紹介しますが、
ModalBottomSheet は内部でシートを閉じるバック処理を持っていて、Android 16+ ではこれが BackHandlerNavHost の自動ポップより先に動いてしまいます。
また、ModalBottomSheet は独立した Dialog ウィンドウとして表示されるため、content のに置いた BackHandler はシートが前面にいる間は呼ばれません。

解決法

shouldDismissOnBackPress = false を設定しつつ、BackHandlercontent 内・NavHost の後 に置きます。

ModalBottomSheet(                                                                                                               
    onDismissRequest = { hideAndDismiss() },
    properties = ModalBottomSheetProperties(shouldDismissOnBackPress = false),                                                    
) {                                                                                                                               
    NavHost(navController = innerNavController, ...) { /* 各画面 */ }                                                             
                                                                                                                                  
    // NavHost 2.8+ はバックスタックを自力でポップするので、ここではルート画面でシートを閉じるだけでいい                                                                               
    val currentEntry by innerNavController.currentBackStackEntryAsState()                                                         
    BackHandler(                                                                                                                  
        enabled = currentEntry != null && innerNavController.previousBackStackEntry == null,                                      
    ) {                                                                                                                           
        hideAndDismiss()                                                                                                          
    }                                                                                                                             
}  
previousBackStackEntry は Compose の state ではないので、currentBackStackEntryAsState() を同じスコープで読んで recompose          

を引き起こす必要があります。これを忘れると enabled が初回コンポーズ時の値のまま更新されません。

おまけ

最初に shouldDismissOnBackPress = false                                                                                         

だけ設定したら、ネスト画面からのバックは直ったもののルート画面でシートが閉じなくなりました。

次に BackHandler を ModalBottomSheet の外に条件付きで置く方法を試したら、ログを仕込んで確認するとコールバックが一度も呼ばれていませんでした(Dialog
ウィンドウが前面にいる間は Activity 側の dispatcher にバックが届かないため)。

結局、両方セットで対応するのが正解でした。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?