5、Compose 里实现 Slide气泡
有两种方式实现气泡
1、是写一个box布局根据Slide拖动计算位置,实现气泡
2、写两个Slider组件用Box包住,将底下那个Slider的thumb自定义后往上移动
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SliderWithBubble(
sliderPosition: Float,
enable: Boolean,
actTrackColors: Color,
inactTrackColors: Color,
onSliderEvent: (Float) -> Unit
) {
Box {
var currentPosition = sliderPosition
var showBubble by remember { mutableStateOf(false) }
// 这个实在底下的那个Slider,大部分不可见,只有Thumb上移的这个地方可以看见
Slider(
modifier = Modifier.size(1126.dp, 74.dp),
valueRange = -5f..5f,
value = currentPosition,
onValueChange = { it ->
currentPosition = it
},
thumb = { // 自定义thumb 使用box
if (showBubble) {
Column(
modifier = Modifier.offset(y = (-70).dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.width(64.dp)
.height(64.dp)
.clip(RoundedCornerShape(100))
.background(sliderActiveThumbBubbleColors),
contentAlignment = Alignment.Center
) {
Text(
modifier = Modifier.size(50.dp),
color = customColors.textColor,
fontSize = 32.sp,
textAlign = TextAlign.Center,
softWrap = true,
text = currentPosition.roundToInt().toString()
)
}
Row {
DrawInvertedTriangle(5.dp, customColors.sliderActiveThumbBubble)
}
}
} else {
Column(
modifier = Modifier
.width(64.dp)
.height(64.dp)
.clip(RoundedCornerShape(20.dp))
.background(Color.Transparent)
) {}
}
}
)
// use box show bubble
/*val bubbleOffset = Offset(
x = (((600 / 11 + (600 % 11) * 0.1) * sliderPosition).toFloat()).roundToInt().toFloat(),
y = (-2).dp.value
)
if (showBubble) {
Column(
modifier = Modifier.offset(bubbleOffset.x.dp, (-8).dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.width(64.dp)
.height(65.dp)
.clip(RoundedCornerShape(20.dp))
.background(Color.Black),
contentAlignment = Alignment.Center
) {
Text(
color = Color.White,
text = sliderPosition.roundToInt().toString()
)
}
Row {
DrawInvertedTriangle(5.dp, Color.Black)
}
}
}*/
// 用户可以看见的Slider,
Slider(
modifier = Modifier.size(1126.dp, 74.dp),
valueRange = -5f..5f,
value = currentPosition,
onValueChange = { newPosition ->
onSliderEvent(newPosition)
showBubble = true
},
onValueChangeFinished = {
showBubble = false
},
steps = 9,
enabled = enable,
thumb = {
Box(
modifier = Modifier
.width(64.dp)
.height(64.dp)
.clip(RoundedCornerShape(100))
.background(customColors.sliderActiveThumb),
contentAlignment = Alignment.Center
) {
Text(
modifier = Modifier.size(50.dp),
color = customColors.pureBlack,
fontSize = 32.sp,
textAlign = TextAlign.Center,
softWrap = true,
text = currentPosition.roundToInt().toString()
)
}
},
track = { sliderPositions ->
SliderDefaults.Track(
modifier = Modifier
.scale(scaleX = 1f, scaleY = 2f),
sliderPositions = sliderPositions,
colors = SliderDefaults.colors(
//滑动条头部的颜色
// thumbColor = Color.Red,
//滑动轨道的颜色
activeTrackColor = actTrackColors,
inactiveTrackColor = inactTrackColors,
//滑动轨道上刻度尺的颜色
activeTickColor = sliderActiveTickColors,
inactiveTickColor = sliderActiveTickColors,
),
)
}
)
}
}
@Composable
fun DrawInvertedTriangle(sz: Dp, cr: Color) {
Canvas(modifier = Modifier.size(sz)) {
val path = Path().apply {
moveTo(0f, 0f) // 移动到顶点
lineTo(size.width, 0f) // 画出左边的线
lineTo(size.width / 2, size.height) // 画出右边的线
close() // 闭合路径
drawPath(this, cr)
}
drawPath(
path = path,
color = cr,
style = Stroke(width = 2.dp.toPx())
)
}
}