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
相关产品推荐
相关产品推荐

