我知道如何使用 BottomSheetScaffold
在 Material 2 Jetpack Compose 中实现 BottomSheet。
但是在 Material 3 中没有 BottomSheetScaffold
。此外,在官方示例中也没有关于 BottomSheet 的内容。
我知道如何使用 BottomSheetScaffold
在 Material 2 Jetpack Compose 中实现 BottomSheet。
但是在 Material 3 中没有 BottomSheetScaffold
。此外,在官方示例中也没有关于 BottomSheet 的内容。
所以我成功地让它工作了!
截至今天,BottomSheetScaffold在Material3上似乎还没有可用的版本,这个问题在我找到的这个issue中有所讨论:https://issuetracker.google.com/issues/229839039
我摘录了谷歌开发者回复中的重要部分:
Swipeable不是很容易使用。目前它有一些需要解决的关键性错误(我们正在解决这个问题),这就是为什么我们在M3中限制了我们暴露给Swipeable的表面。未来几个月,我们计划专注于这个特定领域,并提高开发人员的体验。
Jetpack Compose的Material 3仍处于alpha阶段-这意味着我们认为组件已经可以投入生产,但API形状在alpha阶段是灵活的。这给了我们空间进行迭代,同时从开发人员那里获得现实反馈,最终有助于改善您的体验。 在等待组件被(完全)实现或在alpha版本中公开之前,复制粘贴源代码可能是一个好方法! 拥有源代码,同时API形状仍然是灵活的,会带给您许多好处,如易于更新依赖项,即使API发生变化,并允许您以自己的速度发展组件。
所以我只是按照建议复制粘贴了 BottomSheetScaffold
到我的项目中。当然,由于缺少一些类和一些小的API更改,它不会立即工作。最后,我通过拉取和修改以下类并将它们添加到我的项目中,成功让它工作了:
BottomSheetScaffold.kt
Drawer.kt
Strings.kt
Swipeable.kt
如果您想尝试,我创建了一个gist包含源代码:https://gist.github.com/Marlinski/0b043968c2f574d70ee6060aeda54882
您需要更改导入以使其在您的项目中工作,并通过在gradle文件的android {}
部分中添加以下选项来添加"-Xjvm-default=all"
:
android{
...
kotlinOptions {
freeCompilerArgs += ["-Xjvm-default=all"]
// "-Xjvm-default=all" option added because of this error:
// ... Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option
// triggered by porting BottomSheetScaffold for Material3 on Swipeable.kt:844
}
}
对我来说它非常有效,直到在material3中得到官方支持之前,我将继续使用此解决方案。
希望这可以帮到你!
M3
中可用。 - IgorGanapolsky我们在Material3中终于有了ModalBottomSheet。
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
// Sheet content
if (openBottomSheet) {
ModalBottomSheet(
onDismissRequest = { openBottomSheet = false },
sheetState = bottomSheetState,
) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Button(
// Note: If you provide logic outside of onDismissRequest to remove the sheet,
// you must additionally handle intended state cleanup, if any.
onClick = {
scope.launch { bottomSheetState.hide() }.invokeOnCompletion {
if (!bottomSheetState.isVisible) {
openBottomSheet = false
}
}
}
) {
Text("Hide Bottom Sheet")
}
}
}
}
更多阅读:链接。
androidx.compose.material3:material3:1.1.0-alpha08
中使用。 - Andrei Randroidx.compose.material3:material3:1.1.0-alpha08
版本以后,你不能使用 rememberSheetState
和 skipHalfExpanded
,所以你应该将代码从 val bottomSheetState = rememberSheetState(skipHalfExpanded = true)
修改为 val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
。 - Andrei R更新 2023年2月23日
自Compose Material3版本1.1.0-alpha06起,ModalBottomSheet 现已作为实验性的组合部件可用(文档)。
我使用带有AnimatedVisibility的全屏对话框获得了非常相似的结果,如果感兴趣,这是代码:
// Visibility state for the dialog which will trigger it only once when called
val transitionState = remember {
MutableTransitionState(false).apply {
targetState = true
}
}
Dialog(
onDismissRequest = {} // You can set a visibility state variable to false in here which will close the dialog when clicked outside its bounds, no reason to when full screen though,
properties = DialogProperties(
// This property makes the dialog full width of the screen
usePlatformDefaultWidth = false
)
) {
// Visibility animation, more information in android docs if needed
AnimatedVisibility(
visibleState = transitionState,
enter = slideInVertically(
initialOffsetY = { it },
animationSpec = ...
),
exit = slideOutVertically(
targetOffsetY = { it },
animationSpec = ...
)
)
) {
Box(
modifier = Modifier.fillMaxSize().background(color = ...)
) {
// Your layout
// This can be any user interraction that closes the dialog
Button(
transitionState.apply { targetState = false }
) ...
}
}
onDismissRequest
中添加关闭操作,否则按系统返回按钮将无法关闭对话框。 - bompfBottomSheetScaffold 可在 1.1.0-alpha08
版本中使用。
请参见 https://developer.android.com/jetpack/androidx/releases/compose-material3#1.1.0-alpha08。
M2的BottomSheetScaffold现在已经成为M3的一部分,作为实验性API
以下是一个使用示例
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.rememberCoroutineScope
val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState()
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight = 128.dp,
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 = {
scope.launch { scaffoldState.bottomSheetState.partialExpand() }
}
) {
Text("Click to collapse sheet")
}
}
}) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
Text("Scaffold Content")
}
}
导入:
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material3.ModalBottomSheet
代码
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetDemo(title: String, modifier: Modifier = Modifier) {
ModalBottomSheet(onDismissRequest = { /* Executed when the sheet is dismissed */ }) {
// Sheet content
}
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
var showBottomSheet by remember { mutableStateOf(false) }
Scaffold(
floatingActionButton = {
ExtendedFloatingActionButton(
text = { Text(title) },
icon = { Icon(Icons.Filled.Add, contentDescription = "") },
onClick = {
showBottomSheet = true
}
)
}
) { contentPadding ->
// Screen content
Box(modifier = Modifier.padding(contentPadding)) { /* ... */ }
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")
}
}
}
}
}
ModalBottomSheet
和一个BottomSheetScaffold
。感谢您在Material 3上发布关于这两个组件的内容,我们明白了,真希望我能给你点赞*2。 - Tonnie
BottomSheetScaffold
在Material 3中尚未可用。 - Abhimanyumaterial3:1.0.0-alpha16
进行了检查,发现 BottomSheetScaffold 在 Material 3 上还不可用。 - Tonnie