Hi everybody, is there any solution with compose to check if a path on the canvas was touched? My pa...
c
Hi everybody, is there any solution with compose to check if a path on the canvas was touched? My paths are drawing the cantons of switzerland, which makes using bounding rectangles not a viable solution. My current implementation checks for the location of the touch and compares it to the location of the text elements, which works quite well, but being able to correctly match touch to path could propably be a better solution.
m
I use https://github.com/locationtech/jts for that purpose.
e
if you bridge over to an
android.graphics.Path
, you can use the old
android.graphics.Region
API:
Copy code
val paths = mapOf(
    "a" to Path().apply {
        addRect(Rect(100.0f, 100.0f, 400.0f, 500.0f))
    },
    "b" to Path().apply {
        addArc(
            oval = Rect(400.0f, 500.0f, 600.0f, 700.0f),
            startAngleDegrees = 0.0f,
            sweepAngleDegrees = 360.0f,
        )
    },
    "c" to Path().apply {
        addRoundRect(RoundRect(500.0f, 200.0f, 700.0f, 400.0f, CornerRadius(25.0f)))
    },
)

Canvas(
    modifier = Modifier
        .fillMaxSize()
        .pointerInput(paths) {
            val boundingRegion = Region(0, 0, size.width, size.height)
            val regions = paths.mapValues { (_, path) ->
                Region().apply { setPath(path.asAndroidPath(), boundingRegion) }
            }
            detectTapGestures { (x, y) ->
                val key = regions.entries.find { (_, region) ->
                    region.contains(x.roundToInt(), y.roundToInt())
                }?.key
                Log.i("Canvas", "tap($key)")
            }
        }
) {
    val random = Random(1)
    for (path in paths.values) {
        drawPath(
            path = path,
            color = Color.hsv(hue = random.nextFloat() * 255.0f, saturation = 1.0f, value = 1.0f),
            style = Fill,
        )
    }
}