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におけるボトムシート

Posted at

ModalBottomSheetLayout

androidx.compose.material用のボトムシートとして用意されているコンポーザブルです。
ScaffoldやBoxなど通常で画面に表示される要素をwrapします。
rememberModalBottomSheetState()でボトムシートの状態を作っています。
initialValueでModalBottomSheetValue.Hiddenを指定して隠れた状態にしておき、skipHalfExpandedで中間状態(ボトムシートで画面の一部が隠された状態)にできるかどうかを指定しています。
開閉アクションがのshowとhideがsuspend関数なのでrememberCoroutineScope()でscope変数を作る必要があります。
sheetContentにボトムシートで表示される内容を指定します。
フルモーダル表示にするには内部のコンテンツにModifier.fillMaxSize()を指定すると良いです。

ModalBottomSheetLayout.kt
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文などで表示するかどうかを別要素として管理すれば良いので、書き方が分かりやすくなった気がします。
他の違いなどはこちらが参考になりました。

ModalBottomSheetSample.kt
    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

何かのボタンをタップした時に一時的に表示するボトムシートでなく、常に表示しておきたい時に使うボトムシートです。
スクロールして一部開いておいたり、ほとんど隠した状態にできるもの。

BottomSheetScaffold.kt
    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)
                )
            }
        }
    }
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?