Jetpack Compose 扩展 BottomSheetScaffold 的 BottomSheet 仅在重组后有效
Jetpack Compose expanding BottomSheet of BottomSheetScaffold only works after recomposition
我试图找到一种方法来在我的应用程序中的任何地方显示 BottomSheet,为此我使用 BottomSheetScaffold
和一个 LiveData 对象,该对象包含当前可组合函数,该函数被观察为状态:
val sheetContent by MusicHub.state.bottomSheet.getContent().observeAsState()
BottomSheetScaffold(
modifier = Modifier
.fillMaxSize(),
scaffoldState = bottomSheetScaffoldState,
sheetPeekHeight = 0.dp,
sheetContent = sheetContent!!
)
我在我的应用程序中使用 BottomSheet 作为上下文菜单。例如,当我在我的应用程序中长按播放列表时,它会设置 BottomSheet 的内容并像这样显示:
PlaylistItem(
// ...
onLongClick = {
// Set the LiveData composable
MusicHub.state.bottomSheet.setContent {
PlaylistContextMenuTest(playlist!!, viewModel)
}
// Expand BottomSheet
scope.launch {
MusicHub.state.bottomSheet.expand()
}
}
)
一般来说这是可行的,但 BottomSheet 第一次展开时会显示一瞬间,然后再次消失在底部。这是一个小 GIF:
我的猜测是 BottomSheet 的大小尚未重新计算,因此它仅在下一次重组时有效。来自网络开发人员,我会说它是 requestAnimationFrame 的典型案例,但我不太清楚如何在 compose 中解决这个问题。
编辑:
PlaylistContextMenu测试代码:
@Composable
fun PlaylistContextMenuTest(playlist: Playlist, viewModel: LibraryViewModel = activityViewModel()){
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxWidth()
.navigationBarsPadding()
// TODO: Replace that with a percentage of the screen height
.heightIn(max = 384.dp)
.verticalScroll(scrollState),
content = {
ContextMenu {
repeat(4){
addOption(R.drawable.ic_delete_black_24dp, "Delete"){
Timber.d("Delete Playlist")
viewModel.deletePlaylist(playlist)
}
}
}
}
)
}
完整上下文菜单来源:(https://pastebin.com/sg4ed96L)
你似乎是对的。第一次好像是重新计算BottomSheet的高度。
由于这在第二次尝试时没有改变,因此会显示。
this answer对你有帮助吗?
对于 BottomSheetScaffold 来说似乎还不错,但对于 ModalBottomSheetLayout 却不行(我正在寻找的东西,您可以在链接答案的评论中看到)。
编辑:Accompanist's Navigation Material 也值得一看。
新版本的 Jetpack Compose 已解决此问题。我不确定它是 Beta 8 还是 Beta 9,但现在一切正常。
我试图找到一种方法来在我的应用程序中的任何地方显示 BottomSheet,为此我使用 BottomSheetScaffold
和一个 LiveData 对象,该对象包含当前可组合函数,该函数被观察为状态:
val sheetContent by MusicHub.state.bottomSheet.getContent().observeAsState()
BottomSheetScaffold(
modifier = Modifier
.fillMaxSize(),
scaffoldState = bottomSheetScaffoldState,
sheetPeekHeight = 0.dp,
sheetContent = sheetContent!!
)
我在我的应用程序中使用 BottomSheet 作为上下文菜单。例如,当我在我的应用程序中长按播放列表时,它会设置 BottomSheet 的内容并像这样显示:
PlaylistItem(
// ...
onLongClick = {
// Set the LiveData composable
MusicHub.state.bottomSheet.setContent {
PlaylistContextMenuTest(playlist!!, viewModel)
}
// Expand BottomSheet
scope.launch {
MusicHub.state.bottomSheet.expand()
}
}
)
一般来说这是可行的,但 BottomSheet 第一次展开时会显示一瞬间,然后再次消失在底部。这是一个小 GIF:
我的猜测是 BottomSheet 的大小尚未重新计算,因此它仅在下一次重组时有效。来自网络开发人员,我会说它是 requestAnimationFrame 的典型案例,但我不太清楚如何在 compose 中解决这个问题。
编辑:
PlaylistContextMenu测试代码:
@Composable
fun PlaylistContextMenuTest(playlist: Playlist, viewModel: LibraryViewModel = activityViewModel()){
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxWidth()
.navigationBarsPadding()
// TODO: Replace that with a percentage of the screen height
.heightIn(max = 384.dp)
.verticalScroll(scrollState),
content = {
ContextMenu {
repeat(4){
addOption(R.drawable.ic_delete_black_24dp, "Delete"){
Timber.d("Delete Playlist")
viewModel.deletePlaylist(playlist)
}
}
}
}
)
}
完整上下文菜单来源:(https://pastebin.com/sg4ed96L)
你似乎是对的。第一次好像是重新计算BottomSheet的高度。
由于这在第二次尝试时没有改变,因此会显示。
this answer对你有帮助吗?
对于 BottomSheetScaffold 来说似乎还不错,但对于 ModalBottomSheetLayout 却不行(我正在寻找的东西,您可以在链接答案的评论中看到)。
编辑:Accompanist's Navigation Material 也值得一看。
新版本的 Jetpack Compose 已解决此问题。我不确定它是 Beta 8 还是 Beta 9,但现在一切正常。