android Compose 自定义滑动进度条
androidx.compose.material3 我用1.2.0版本的Slider非常好用,但是升级到1.3.2后滑轨后面多了个点,滑块背景也移除不掉而且默认透明了我暂时没有找到让他不透明。所以自定义了一个先用着。
@Composable fun CustomSlider( state: CustomSliderState, modifier: Modifier = Modifier, trackHeight: Dp = 4.dp, thumbSize: Dp = 24.dp, trackColor: Color = Color.Gray, progressColor: Color = Color.Blue, thumbColor: Color = Color.White, onValueChange: ((Float) -> Unit)? = null, onValueChangeFinished: ((Float) -> Unit)? = null ) { var sliderWidth by remember { mutableFloatStateOf(0f) } Box( modifier = modifier .height(thumbSize + 16.dp) // 确保足够高度容纳滑块 .pointerInput(Unit) { awaitEachGesture { http://www.devze.com val event = awaitPointerEvent(PointerEventPass.Initial) if (event.changes.firstOrNull()?.changedToDown() == true) { val down = awaitFirstDown(requireUnconsumed = true) state.setPressed(true) val newposition = (event.changes.first().position.x / sliderWidth).coerceIn(0f, 1f) val newValue = state.range.start + newPosition * (state.range.endInclusive - state.range.start) state.updateValue(newValue) onValueChange?.invoke(state.value) var drag: PointerInputChange? do { drag = awaitTouchSlopOrCancellation(down.id) { change, _ -> if (change.positionChange() != Offset.Zero) change.consume() } } while (drag != null && !drag.isConsumed) if (drag != null) { val dragResult = drag(drag.id) {编程 val newPosition = (it.position.x / sliderWidth).coerceIn(0f, 1f) val newValue = state.range.start + newPosition * (state.range.endInclusive - state.range.start) state.updateValue(newValue) onValueChange?.invoke(state.value) } // 确保完成回调被触发 if (!dragResult || drag.isConsumed) { onValueChangeFinished?.invoke(state.value) } } else { onValueChangeFinished?.invoke(state.value) } } } }, contentAlignment = Alignment.CenterStart ) { // 绘制轨道(Track) Canvas( modifier = Modifier .fillMaxWidth() .clip(CircleShape) .height(trackHeight) .align(Alignment.CenterStart) .onSizeChanged { size -> sliderWidth = size.width.toFloat() } ) { // 背景轨道 drawRect( color = trackColor, size = Size(size.width.toFloat(), trackHeight.toPx()) ) // 进度轨道 drawRect( color = progressColor, size = Size( width = (state.value - state.range.start) / (state.range.endInclusive - state.range.start) * size.width, height = trackHeight.toPx() ) ) } // 滑块(Thumb)根据你自己需求替换 Box( modifier = Modifier .offset { IntOffset( x = ((state.value - state.range.start) / (state.range.endInclusive - state.range.start) * sliderWidth - thumbSize.toPx()/2).toInt(), y = 0 ) } .shadow(4.dp, CircleShape) .size(thumbSize) .background(thumbColor, CircleShape) ) } } class CustomSliderState( initialValue: Float, interwww.devze.comnal val range: ClosedFloatingPointRange<Float> = 0f..1f ) { private val _value = mutableFloatStateOf(initialValue.coerceIn(range)) private val _isPressed = mutableStateOf(false) // 新增按下状态 val value: Float get() = _value.floatValue val isPressed: Boolean // 暴露给外部 get() = _isPressed.value fun updateValue(newValue: Float) { _value.floatValue = newValue.coerceIn(range) } fun setPressed(pressed: Boolean) { // 更新按下状态 _isPressed.value = pressed } } @Composable fun rememberCustomSliderState( initialValue: Float = 0f, range: ClosedFloatingPointRange<Float> = 0f..1f ): CustomSliderState { return remember { CustomSliderState(initialValue, range) } }
使用
val sliderState = rememberCustomSliderState( initialValue = 0.5f, range = 0f..100f ) CustomSlider( state = sliderState, modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp), trackHeight = 12.dp, thumbSize = 24.dp, trackColor = Color.LightGray, progressColor = Color(0xFF6200EE), thumbColor = Color.White, onValueChange = { Log.e("onValueChange","float---$it") }, onValueChangeFinished = { Log.e("onValueChangeFinished","float---$it") } )
补充:Compose笔记(十五)--进度条
这一节了解一下Compose中的进度条,有两种类型的进度条可供使用,分别是线性进度条(LinearProgressIndicator)和圆形进度条(CircularProgressIndicator),每种进度条又可分为确定模式和不确定模式。
1. 不确定模式
在不确定模式下,进度条会持续滚动,用于表示操作正在进行,但无法确定具体的完成进度。2. 确定模式在确定模式下,需要传入 progress 参数,该参数的值范围是 0 到 1,表示操作的完成进度。栗子:
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.LinearProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @Composable fun ProgressBarsExample() { Column( modifier = Modifier.padding(top = 40.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // 不确定线性进度条 IndeterminateLinearProgressBar() // 确定线性进度条 DeterminateLinearProgressBar() // 不确定圆形进度条 IndeterminateCirculhttp://www.devze.comarProgressBar() // 确定圆形进度条 DeterminateCircularProgressBar() // 自定义进度条样式 CircularProgressBarExample() } } @Composable fun IndeterminateLinearProgressBar() { LinearProgressIndicator() } @Composable fun DeterminateLinearProgressBar() { var progress by remember { mutableStateOf(0.5f)} LinearProgressIndicator( progress = progress ) } @Composable fun IndeterminateCircularProgressBar() { CircularProgressIndicator() } @Composable fun DeterminateCircularProgressBar() { var progress by remember { mutableStateOf(0.7f)} CircularProgressIndicator( progress = progress ) }
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable fun CircularProgressBarExample() { var progress by remember { mutableStateOf(0.2f) } Column( modifier = Modifier.size(400.dp).padding(top = 20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { CircularProgressBar( progress = progress, modifier = Modifier.size(150.dp), indicatorStrokeWidth = 4.dp, backgroundCircleColor = if(progress in 0.0..0.2) Color.Yellow else if(progress>0.2 && progress<=0.5) Color.Red else if(progress>0.5 && progress<0.8) Color.Blue else Color.White, fontSize = 12.sp ) Button( modifier = Modifier.padding(top = 20.dp), onClick = { progress = if (progress < 1f) progress + 0.1f else 0f } ) { Text(text = "进度测试") } } }
import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.Box import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import androidx.compose.ui.unihttp://www.devze.comt.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable fun CircularProgressBar( progress: Float, modifier: Modifier = Modifier, backgroundIndicatorColor: Color = Color.LightGray, indicatorColor: Color = Color.Blue, indicatorStrokeWidth: Dp = 10.dp, backgroundCircleColor: Color = Color.White, textColor: Color = Color.Black, fontSize: TextUnit = 20.sp ) { Box( modifier = modifier, contentAlignment = Alignment.Center ) { Canvas(modifier = modifier) { drawBackgroundCircle(backgroundCircleColor) drawBackgroundIndicator(backgroundIndicatorColor, indicatorStrokeWidth) drawProgressIndicator(progress, indicatorColor, indicatorStrokeWidth) } Text( text = "${(progress * 100).toInt()}%", color = textColor, fontSize = fontSize, fontWeight = FontWeight.Bold ) } } private fun DrawScope.drawBackgroundCircle(color: Color) { drawCircle( color = color, radius = size.minDimension / 2 ) } private fun DrawScope.drawBackgroundIndicator( color: Color, strokeWidth: Dp ) { drawArc( color = color, startAngle = -90f, sweepAngle = 360f, useCenter = false, style = Stroke( width = strokeWidth.toPx(), cap = StrokeCap.Round ), size = Size(size.width, size.height) ) } private fun DrawScope.drawProgressIndicator( progress: Float, color: Color, strokeWidth: Dp ) { drawArc( color = color, startAngle = -90f, sweepAngle = 360f * progress, useCenter = false, style = Stroke( width = strokeWidth.toPx(), cap = StrokeCap.Round ), size = Size(size.width, size.height) ) }
如图:
到此这篇关于Android Compose 自定义滑动进度条的文章就介绍到这了,更多相关Android Compose滑动进度条内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论