我需要准备一个圆形滑块的UI,我可以通过值或移动,拖动指针在滑块中滑动类似于所附的截图。的数据
的我怎么才能做到呢?
qoefvg9y1#
你可以看看这个快速解决方案。我在右边有0度,但你可以颠倒象限以满足你的需要。
@Composable fun Content() { var radius by remember { mutableStateOf(0f) } var shapeCenter by remember { mutableStateOf(Offset.Zero) } var handleCenter by remember { mutableStateOf(Offset.Zero) } var angle by remember { mutableStateOf(20.0) } Canvas( modifier = Modifier .fillMaxSize() .pointerInput(Unit) { detectDragGestures { change, dragAmount -> handleCenter += dragAmount angle = getRotationAngle(handleCenter, shapeCenter) change.consume() } } .padding(30.dp) ) { shapeCenter = center radius = size.minDimension / 2 val x = (shapeCenter.x + cos(Math.toRadians(angle)) * radius).toFloat() val y = (shapeCenter.y + sin(Math.toRadians(angle)) * radius).toFloat() handleCenter = Offset(x, y) drawCircle(color = Color.Black.copy(alpha = 0.10f), style = Stroke(20f), radius = radius) drawArc( color = Color.Yellow, startAngle = 0f, sweepAngle = angle.toFloat(), useCenter = false, style = Stroke(20f) ) drawCircle(color = Color.Cyan, center = handleCenter, radius = 60f) } } private fun getRotationAngle(currentPosition: Offset, center: Offset): Double { val (dx, dy) = currentPosition - center val theta = atan2(dy, dx).toDouble() var angle = Math.toDegrees(theta) if (angle < 0) { angle += 360.0 } return angle }
字符串
的数据
2ekbmq322#
在Github上查看这个code中的解决方案。只需替换Canvas中的Angular 值。
omhiaaxx3#
Circular scrollable Progress bar / Circular slider代码:
import android.view.MotionEvent import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.size 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.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.unit.dp import kotlin.math.PI import kotlin.math.abs import kotlin.math.atan2 import kotlin.math.min val ColorPrimary = Color(0xFF1c2026) val LightGreen = Color(0xFF8dc387) val ProgressBarBg = Color(0xFFFFE9DD) val ProgressBarProgress = Color(0xFFE08868) val ProgressBarTint = Color(0xFFE1BAAA) @OptIn(ExperimentalComposeUiApi::class) @Composable fun MuneerCircularProgressBar( modifier: Modifier = Modifier, padding: Float = 50f, stroke: Float = 35f, cap: StrokeCap = StrokeCap.Round, initialAngle : Double = 0.0, onProgressChanged: (progress: Double) -> Unit, ) { var width by remember { mutableStateOf(0) } var height by remember { mutableStateOf(0) } var radius by remember { mutableStateOf(0f) } var center by remember { mutableStateOf(Offset.Zero) } var appliedAngle by remember { mutableStateOf(initialAngle) } var lastAngle by remember { mutableStateOf(0.0) } Canvas(modifier = modifier .size(270.dp) .onGloballyPositioned { width = it.size.width height = it.size.height center = Offset(width / 2f, height / 2f) radius = min(width.toFloat(), height.toFloat()) / 2f - padding - stroke / 2f } .pointerInteropFilter { when (it.action) { MotionEvent.ACTION_DOWN -> { } MotionEvent.ACTION_MOVE -> { appliedAngle = if (center.x > it.x && center.y > it.y) { 270 + deltaAngle(center.x - it.x, center.y - it.y) } else { 90 - deltaAngle(it.x - center.x, center.y - it.y) } val diff = abs(lastAngle - appliedAngle) if (diff > 180) { appliedAngle = if (appliedAngle < 180) { 360.0 } else { 0.0 } } onProgressChanged(appliedAngle / 360.0) lastAngle = appliedAngle } MotionEvent.ACTION_UP -> { } else -> return@pointerInteropFilter false } return@pointerInteropFilter true } ) { drawArc( color = ProgressBarBg, startAngle = -90f, sweepAngle = 360f, useCenter = false, topLeft = center - Offset(radius, radius), size = Size(radius * 2, radius * 2), style = Stroke( width = stroke, cap = cap ) ) drawArc( color = ProgressBarProgress, startAngle = -90f, sweepAngle = abs(appliedAngle.toFloat()), topLeft = center - Offset(radius, radius), size = Size(radius * 2, radius * 2), useCenter = false, style = Stroke( width = stroke, cap = cap ) ) drawCircle( color = ProgressBarTint, radius = stroke, center = center + Offset( radius * kotlin.math.cos((-90 + abs(appliedAngle)) * PI / 180f).toFloat(), radius * kotlin.math.sin((-90 + abs(appliedAngle)) * PI / 180f).toFloat() ) ) drawCircle( color = ColorPrimary, radius = ((stroke*2.0)/3.0).toFloat(), center = center + Offset( radius * kotlin.math.cos((-90 + abs(appliedAngle)) * PI / 180f).toFloat(), radius * kotlin.math.sin((-90 + abs(appliedAngle)) * PI / 180f).toFloat() ) ) drawLine( color = LightGreen, start = center + Offset( (radius-10) * kotlin.math.cos((-90 + abs(appliedAngle)) * PI / 180f).toFloat(), (radius-10) * kotlin.math.sin((-90 + abs(appliedAngle)) * PI / 180f).toFloat() ), end = center + Offset( (radius+10) * kotlin.math.cos((-90 + abs(appliedAngle)) * PI / 180f).toFloat(), (radius+10) * kotlin.math.sin((-90 + abs(appliedAngle)) * PI / 180f).toFloat() ) ) } } fun deltaAngle(x: Float, y: Float): Double { return Math.toDegrees(atan2(y.toDouble(), x.toDouble())) }
3条答案
按热度按时间qoefvg9y1#
你可以看看这个快速解决方案。我在右边有0度,但你可以颠倒象限以满足你的需要。
字符串
的数据
2ekbmq322#
在Github上查看这个code中的解决方案。只需替换Canvas中的Angular 值。
omhiaaxx3#
Circular scrollable Progress bar / Circular slider
代码:
字符串