ModalBottomSheetLayout
androidx.compose.material
用のボトムシートとして用意されているコンポーザブルです。
ScaffoldやBoxなど通常で画面に表示される要素をwrapします。
rememberModalBottomSheetState()でボトムシートの状態を作っています。
initialValueでModalBottomSheetValue.Hiddenを指定して隠れた状態にしておき、skipHalfExpandedで中間状態(ボトムシートで画面の一部が隠された状態)にできるかどうかを指定しています。
開閉アクションがのshowとhideがsuspend関数なのでrememberCoroutineScope()でscope変数を作る必要があります。
sheetContentにボトムシートで表示される内容を指定します。
フルモーダル表示にするには内部のコンテンツにModifier.fillMaxSize()を指定すると良いです。
var skipHalfExpanded by remember { mutableStateOf(false) }
val state =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipHalfExpanded = skipHalfExpanded
)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetState = state,
sheetContent = {
LazyColumn {
items(50) {
ListItem(
text = { Text("Item $it") },
icon = {
Icon(
Icons.Default.Favorite,
contentDescription = "Localized description"
)
}
)
}
}
}
) {
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
Modifier.toggleable(
value = skipHalfExpanded,
role = Role.Checkbox,
onValueChange = { checked -> skipHalfExpanded = checked }
)
) {
Checkbox(checked = skipHalfExpanded, onCheckedChange = null)
Spacer(Modifier.width(16.dp))
Text("Skip Half Expanded State")
}
Spacer(Modifier.height(20.dp))
Button(onClick = { scope.launch { state.show() } }) { Text("Click to show sheet") }
}
}
ModalBottomSheet
Material3用のボトムシートのコンポーザブルです。
基本的にはModalBottomSheetLayoutと同じです。
ModalBottomSheetではボトムシートの状態を自分で管理するため、MutableStateで変数を作成しています。
こちらでは通常の画面をwrapする必要はなく、if文などで表示するかどうかを別要素として管理すれば良いので、書き方が分かりやすくなった気がします。
他の違いなどはこちらが参考になりました。
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
var showBottomSheet by remember { mutableStateOf(false) }
Scaffold(
floatingActionButton = {
ExtendedFloatingActionButton(
text = { Text("Show bottom sheet") },
icon = { Icon(Icons.Filled.Add, contentDescription = "") },
onClick = {
showBottomSheet = true
}
)
}
) { contentPadding ->
// Screen content
if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
},
sheetState = sheetState
) {
// Sheet content
Button(onClick = {
scope.launch { sheetState.hide() }.invokeOnCompletion {
if (!sheetState.isVisible) {
showBottomSheet = false
}
}
}) {
Text("Hide bottom sheet")
}
}
}
}
BottomSheetScaffold
何かのボタンをタップした時に一時的に表示するボトムシートでなく、常に表示しておきたい時に使うボトムシートです。
スクロールして一部開いておいたり、ほとんど隠した状態にできるもの。
val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState()
BottomSheetScaffold(
sheetContent = {
Box(
Modifier
.fillMaxWidth()
.height(128.dp), contentAlignment = Alignment.Center
) {
Text("Swipe up to expand sheet")
}
Column(
Modifier
.fillMaxWidth()
.padding(64.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Sheet content")
Spacer(Modifier.height(20.dp))
Button(onClick = {}) {
Text("Click to collapse sheet")
}
}
},
scaffoldState = scaffoldState,
topBar = {
TopAppBar(title = { Text("Bottom sheet scaffold") })
},
sheetPeekHeight = 128.dp
) { innerPadding ->
LazyColumn(contentPadding = innerPadding) {
items(100) {
Box(
Modifier
.fillMaxWidth()
.height(50.dp)
.background(color = androidx.compose.ui.graphics.Color.Gray)
)
}
}
}