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

Jetpack Compose:如何检测点击的饼图分段及描边宽度默认方向?

一、检测圆形/半圆内点击的弧形分段或角度

核心逻辑是通过计算点击点相对圆心的角度,匹配预先划分的分段区间,同时校验点击点是否落在弧形的描边范围内:

  • 计算点击点与圆心的相对偏移,转换为0-360度的角度(注意Compose坐标系Y轴向下,需适配数学角度计算)
  • 根据整圆/半圆的总角度,拆分出每个分段的角度范围
  • 额外判断点击点到圆心的距离,确保在弧形的内、外半径之间,避免误判空白区域

示例实现(Jetpack Compose)

Canvas(modifier = Modifier
    .size(300.dp)
    .pointerInput(Unit) {
        detectTapGestures { offset ->
            // 圆心坐标
            val center = Offset(size.width / 2, size.height / 2)
            // 点击点相对圆心的偏移量
            val delta = offset - center
            // 计算角度(适配Compose坐标系,转换为0-360度)
            var angle = Math.toDegrees(Math.atan2(delta.y, delta.x))
            if (angle < 0) angle += 360

            // 假设半圆分为4个分段(0-180度,每段45度)
            val segmentCount = 4
            val segmentAngle = 180f / segmentCount
            for (i in 0 until segmentCount) {
                val start = i * segmentAngle
                val end = (i + 1) * segmentAngle
                if (angle in start..end) {
                    println("点击了第${i+1}个分段")
                    break
                }
            }

            // 校验是否在弧形描边范围内
            val arcInnerRadius = size.width / 2 - 20.dp.toPx()
            val arcOuterRadius = size.width / 2
            val distance = delta.getDistance()
            if (distance in arcInnerRadius..arcOuterRadius) {
                // 点击点在有效弧形区域内
            }
        }
    }
) {
    // 绘制半圆分段
    val segmentCount = 4
    val segmentAngle = 180f / segmentCount
    for (i in 0 until segmentCount) {
        drawArc(
            color = if (i%2==0) Color.Blue else Color.Gray,
            startAngle = i * segmentAngle,
            sweepAngle = segmentAngle,
            useCenter = false,
            topLeft = Offset(20.dp.toPx(), 20.dp.toPx()),
            size = Size(size.width - 40.dp.toPx(), size.height - 40.dp.toPx()),
            style = Stroke(width = 40.dp.toPx())
        )
    }
}
二、Canvas/Composable draw Modifier描边宽度的默认方向

默认情况下,描边是居中对齐的:即描边宽度的一半绘制在路径内侧,另一半绘制在外侧。

如果需要指定描边方向,可通过Stroke的align参数调整:

  • StrokeAlign.Inside:描边完全绘制在路径内侧
  • StrokeAlign.Outside:描边完全绘制在路径外侧
  • StrokeAlign.Center(默认值):描边居中分布在路径两侧

示例代码

drawCircle(
    color = Color.Red,
    radius = 100.dp.toPx(),
    style = Stroke(
        width = 20.dp.toPx(),
        align = StrokeAlign.Inside // 仅在内侧绘制描边
    )
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:25:21