Compose 中的 Bottom sheets

342 阅读2分钟

在 Jetpack Compose 中,Bottom Sheet 是一种从屏幕底部滑出的组件,用于显示附加内容或选项。Compose 提供了 ModalBottomSheetLayoutBottomSheetScaffold 组件来创建和管理 Bottom Sheets。

Bottom Sheets 的类型

  1. Modal Bottom Sheets: 覆盖整个屏幕的底部浮层,通常用于显示不需要与其他内容交互的内容。
  2. Persistent Bottom Sheets: 固定在屏幕底部的底部浮层,通常用于显示可与主内容同时交互的信息。

示例代码

下面是一个使用 ModalBottomSheetLayoutBottomSheetScaffold 的示例。

Modal Bottom Sheet

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BottomSheetExampleTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    ModalBottomSheetExample()
                }
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModalBottomSheetExample() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "This is a Modal Bottom Sheet")
            }
        }
    ) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .clickable {
                    scope.launch {
                        sheetState.show()
                    }
                },
            contentAlignment = Alignment.Center
        ) {
            Text(text = "Tap to show Modal Bottom Sheet")
        }
    }
}

@Preview(showBackground = true)
@Composable
fun ModalBottomSheetExamplePreview() {
    BottomSheetExampleTheme {
        ModalBottomSheetExample()
    }
}

Persistent Bottom Sheet

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PersistentBottomSheetExample() {
    val scaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = rememberBottomSheetState(BottomSheetValue.Collapsed)
    )
    val scope = rememberCoroutineScope()

    BottomSheetScaffold(
        scaffoldState = scaffoldState,
        sheetContent = {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "This is a Persistent Bottom Sheet")
            }
        },
        sheetPeekHeight = 0.dp
    ) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.LightGray),
            contentAlignment = Alignment.Center
        ) {
            Button(onClick = {
                scope.launch {
                    if (scaffoldState.bottomSheetState.isCollapsed) {
                        scaffoldState.bottomSheetState.expand()
                    } else {
                        scaffoldState.bottomSheetState.collapse()
                    }
                }
            }) {
                Text(text = "Toggle Bottom Sheet")
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun PersistentBottomSheetExamplePreview() {
    PersistentBottomSheetExample()
}

解释

  1. 状态管理:

    • 使用 rememberModalBottomSheetState 来管理 Modal Bottom Sheet 的状态。
    • 使用 rememberBottomSheetScaffoldStaterememberBottomSheetState 来管理 Persistent Bottom Sheet 的状态。
  2. 布局:

    • ModalBottomSheetLayout 用于创建 Modal Bottom Sheet。它包含 sheetContent 参数用于定义底部浮层的内容。
    • BottomSheetScaffold 用于创建 Persistent Bottom Sheet。它包含 sheetContentsheetPeekHeight 参数。
  3. 控制 Bottom Sheet 显示和隐藏:

    • 使用 CoroutineScopelaunch 函数来控制 Bottom Sheet 的显示和隐藏。
    • sheetState.show()sheetState.hide() 分别用于显示和隐藏 Modal Bottom Sheet。
    • bottomSheetState.expand()bottomSheetState.collapse() 分别用于展开和折叠 Persistent Bottom Sheet。

自定义样式

你可以通过自定义参数来调整 Bottom Sheet 的外观,例如高度、背景颜色等。利用这些参数可以实现更符合设计需求的底部浮层。