はじめに
Android Jetpack Composeで、下スワイプで画面を閉じる方法を解説。ModalBottomSheet
を用いる方法もあるが、この記事ではAnchoredDraggableState
によりスワイプ検知して画面を閉じる方法について解説。
方法
1. スワイプ開始・終了クラスの作成
スワイプ状態を定義するクラス作成。
enum class AnchorPos { Start, End; }
2. モーダル画面の作成
モーダル画面を作成
@OptIn(ExperimentalFoundationApi::class) @Composable fun ModalScreen(navController: NavHostController) { val screenHeight = with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() } val anchors = DraggableAnchors { AnchorPos.Start at 0f AnchorPos.End at screenHeight } // ドラッグ可能な距離と状態を設定 val draggableState = remember { AnchoredDraggableState( initialValue = AnchorPos.Start, anchors = anchors, positionalThreshold = { it * 0.5f }, velocityThreshold = { screenHeight * 0.5f }, snapAnimationSpec = SpringSpec(), decayAnimationSpec = exponentialDecay(), confirmValueChange = { when (it) { AnchorPos.Start -> {} AnchorPos.End -> { //複数回popが行われることを防ぐため、現在の画面でのみpopを行う。 if (navController.currentDestination?.route == NavItem.MODAL.route) { navController.popBackStack() } } } true } ) } Box( modifier = Modifier .offset { IntOffset( x = 0, y = draggableState .requireOffset() .roundToInt() ) } .anchoredDraggable( state = draggableState, orientation = Orientation.Vertical ) .fillMaxSize() .background(Color.DarkGray), ) { //戻るボタン Button( onClick = { navController.popBackStack() }, colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent), contentPadding = PaddingValues(0.dp) ) { Icon( modifier = Modifier.size(32.dp), contentDescription = "Close", imageVector = Icons.Default.Close ) } } }