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

Jetpack Compose自定义可拖动BottomSheet标签形状及zIndex问题

BottomSheet形状融合与zIndex层级问题

设计效果 vs 实际效果(使用Excalidraw制作)

设计效果
当前实际效果

我遇到的是zIndex继承问题。需要让“圆形-标签矩形-圆形”组成的行形成融合形状,需要一个遮挡矩形位于行背景前方、标签矩形后方。但Compose会将遮挡矩形的zIndex与行的基础zIndex比较,而非标签矩形的zIndex,设置后无效。同时欢迎更简洁的解决方案。

初始实现代码

@Composable fun BottomSheetContainer() {
    val sheetState = rememberBottomSheetState(
        initialValue = BottomSheetValue.Collapsed
    )
    val scaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = sheetState
    )
    val scope = rememberCoroutineScope()
    val tabHeight = 36.dp
    val modifier = Modifier
    BottomSheetScaffold(
        scaffoldState = scaffoldState,
        sheetContent = {
            Box(modifier = modifier.fillMaxWidth().height(tabHeight).background(Color.White)) {
                Box(modifier = modifier.align(Alignment.TopCenter).height(tabHeight/2+2.dp).width(130.dp).background(MaterialTheme.colors.background.copy(0.5f)).zIndex(1f))
            Row(modifier = modifier.clip(RoundedCornerShape(tabHeight/2, tabHeight/2, tabHeight/2, tabHeight/2)).height(tabHeight).align(alignment=Alignment.Center).background(Color.Blue)) {

                    Box(
                    modifier = modifier
                        .size(tabHeight)
                        .clip( RoundedCornerShape(tabHeight/2,tabHeight/2,tabHeight/2,tabHeight/2))
                        .background(Color.Red)
                        .zIndex(.3f))
Box(
                modifier = modifier.zIndex(4f)
                    .clip( RoundedCornerShape(tabHeight/2, tabHeight/2, 0.dp, 0.dp))
                    .width(100.dp)
                    .height(tabHeight)
                    .align(Alignment.CenterVertically)
                    .background(color = purple400)

                    ,
                contentAlignment = Alignment.Center
            ){
                Text("^^^",color = Color.Black)
            }
                Box(
                    modifier = Modifier
                        .size(tabHeight)
                        .clip( RoundedCornerShape(tabHeight/2,tabHeight/2,tabHeight/2,tabHeight/2,))
                        .background(MaterialTheme.colors.background.copy(0.5f))
                )
            }}
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(400.dp)
                    .background(color = notepad),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = "Bottom sheet",
                    fontSize = 60.sp
                )
            }
        },
        sheetBackgroundColor = Color.Red.copy(alpha = 0.01f),
        sheetPeekHeight = 30.dp
    ) {
        //the bottom half of the screen, covered by sheet
        Box(
            modifier = Modifier
                .fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Button(onClick = {
                scope.launch {
                    if (sheetState.isCollapsed) {
                        sheetState.expand()
                    } else {
                        sheetState.collapse()
                    }
                }
            }) {
                Text(text = "Bottom sheet fraction: ${sheetState.progress.fraction}")
            }
        }
    }}

进展:接近实现但轮廓不透明

进展效果

更新后的代码

@Composable
fun BottomSheetContainer() {
    val sheetState = rememberBottomSheetState(
        initialValue = BottomSheetValue.Collapsed
    )
    val scaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = sheetState
    )
    val scope = rememberCoroutineScope()
    val tabHeight = 36.dp
    val modifier = Modifier
    BottomSheetScaffold(
        scaffoldState = scaffoldState,
        sheetContent = {
            Box(modifier = modifier.fillMaxWidth().height(tabHeight).background(Color.Transparent)) {
                Box(
                    modifier = modifier.zIndex(4f)
                        .clip( RoundedCornerShape(tabHeight/2, tabHeight/2, 0.dp, 0.dp))
                        .width(100.dp)
                        .height(tabHeight)
                        .align(Alignment.Center)
                        .background(color = notepad)

                    ,
                    contentAlignment = Alignment.Center
                ){
                    Text("^^^",color = Color.Black)
                }
                Box(modifier = modifier.align(Alignment.TopCenter).height(tabHeight/2+2.dp).width(130.dp).background(MaterialTheme.colors.background).zIndex(1f))
            Row(modifier = modifier.clip(RoundedCornerShape(tabHeight/2, tabHeight/2, tabHeight/2, tabHeight/2)).height(tabHeight).align(alignment=Alignment.Center).background(notepad)) {

                    Box(
                    modifier = modifier
                        .size(tabHeight)
                        .clip( RoundedCornerShape(tabHeight/2,tabHeight/2,tabHeight/2,tabHeight/2))
                        .background(MaterialTheme.colors.background)
                        .zIndex(.3f))
                    Box(
                modifier = modifier.zIndex(4f)
                    .clip( RoundedCornerShape(tabHeight/2, tabHeight/2, 0.dp, 0.dp))
                    .width(100.dp)
                    .height(tabHeight)
                    .align(Alignment.CenterVertically)
                    .background(color = notepad)

                    ,
                contentAlignment = Alignment.Center
            ){
                Text("^^^",color = Color.Black)
            }
                Box(
                    modifier = Modifier
                        .size(tabHeight)
                        .clip( RoundedCornerShape(tabHeight/2,tabHeight/2,tabHeight/2,tabHeight/2,))
                        .background(MaterialTheme.colors.background)
                )
            }}
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(400.dp)
                    .background(color = notepad),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = "Bottom sheet",
                    fontSize = 60.sp
                )
            }
        },
        sheetBackgroundColor = Color.Transparent,
        sheetPeekHeight = 30.dp
    ) {
        //the bottom half of the screen, covered by sheet
        Box(
            modifier = Modifier
                .fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Button(onClick = {
                scope.launch {
                    if (sheetState.isCollapsed) {
                        sheetState.expand()
                    } else {
                        sheetState.collapse()
                    }
                }
            }) {

                Text(text = "Bottom sheet fraction: ${sheetState.progress.fraction}")
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Instancer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:55:15