You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jetpack Compose实现Snapchat风格个人资料页底部弹窗的问题求助

Jetpack Compose实现Snapchat风格个人资料页底部弹窗的问题求助

大家好,我刚接触Kotlin和Jetpack Compose,最近一直在折腾一个类似Snapchat的个人资料页——页面顶部是背景头像,下方用底部弹窗展示用户名和其他详情。我试了两种实现方案,但都有一些问题没解决,已经卡了好一阵子了,麻烦大家帮忙指点一下!


方案一:使用ModalBottomSheet

我先尝试了用ModalBottomSheet来实现,代码如下:

@Composable
fun UserScreen() {
    val modalBottomSheet = remember { mutableStateOf(false) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        UserImageView()
    }

    BottomSheet(modalBottomSheet)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheet(showModalBottomSheet: MutableState<Boolean>) {
    rememberCoroutineScope()
    ModalBottomSheet(
        onDismissRequest = { showModalBottomSheet.value = true }
    ) {
        HeadingTextComponent(value = stringResource(id = R.string.username))
        Spacer(modifier = Modifier.height(10.dp))
        CardComponent()
        LazyColumn(Modifier.fillMaxSize()) {
            items(50) { index ->
                Text(
                    text = "Item $index",
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp)
                )
            }
        }
    }
}

这个方案的问题很明显:向下滑动底部弹窗时,它会自动收起,这不符合我想要的效果。


方案二:使用BottomSheetScaffold

之后我换成了BottomSheetScaffold,因为它支持设置sheetPeekHeight来固定初始高度,避免弹窗收起,代码如下:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        MyBottomSheet()
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyBottomSheet() {
    BottomSheetScaffold(
        sheetContent = {
            HeadingTextComponent(value = stringResource(id = R.string.username))
            LazyColumn(
                modifier = Modifier.fillMaxSize()
            ) {
                items(50) { index ->
                    Text(
                        text = "Item $index",
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(16.dp)
                    )
                }
            }
        },
        sheetPeekHeight = 600.dp
    ) {
        UserImageView()
    }
}

这个方案虽然解决了弹窗自动收起的问题,但又出现了新的问题:

  • 当弹窗完全展开时,顶部的圆角仍然显示,看起来很奇怪
  • 弹窗不会覆盖状态栏,导致状态栏区域还能看到弹窗的圆角和底部标识
  • 用力向下滑动弹窗时,会出现短暂的“脱离”页面的效果(这个问题在两个方案里都存在)

我期望实现的效果

我想要的是和Snapchat个人资料页完全一致的底部弹窗效果:

  • 弹窗有固定的初始高度
  • 点击遮罩或者向下滑动时,弹窗不会收起
  • 弹窗完全展开时,顶部的圆角自动消失
  • 拖动弹窗时是平滑的过渡效果,和状态栏之间没有突兀的切换(可以参考Snapchat的底部弹窗交互)

我还准备了相关的截图方便大家理解问题,不过这里暂时没法展示出来。

真心感谢各位的帮助,作为新手真的卡了很久了😭

备注:内容来源于stack exchange,提问作者Digvijay Pratap Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 11:23:10