nuhkoca
05/08/2024, 11:34 PMnuhkoca
05/08/2024, 11:34 PM@Composable
fun LineChart(points: List<Float>, modifier: Modifier = Modifier) {
val touchPoint = remember { mutableStateListOf<Offset>() }
Canvas(
modifier = modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTransformGestures { centroid, pan, _, _ ->
touchPoint += centroid
}
}
) {
val width = size.width
val height = size.height
// Calculate the step for x axis
val stepX = width / (points.size - 1)
// Calculate the step for y axis
val maxY = points.maxOrNull() ?: 1f
val stepY = height / maxY
// Draw line connecting points
points.forEachIndexed { index, point ->
val x = index * stepX
val y = height - point * stepY
if (index < points.size - 1) {
val nextX = (index + 1) * stepX
val nextY = height - points[index + 1] * stepY
drawLine(start = Offset(x, y), end = Offset(nextX, nextY), color = Color.Blue, strokeWidth = 3f)
}
// Draw points
drawCircle(color = Color.Blue, center = Offset(x, y), radius = 6f)
}
touchPoint.forEach {
drawCircle(color = Color.Red, center = it, radius = 30f)
}
}
}
nuhkoca
05/08/2024, 11:36 PMnuhkoca
05/08/2024, 11:37 PMRebecca Franks
05/09/2024, 8:36 AMRebecca Franks
05/09/2024, 8:37 AMevent.changes.forEach
will give you all the pointer events at present.
@Composable
@Preview
fun Multitouch() {
var listPointers = remember { mutableStateListOf<Offset>() }
Box(
Modifier
.size(400.dp)
//.background(Color.Blue)
.pointerInput(Unit) {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
event.changes.forEach {
listPointers.add(it.position)
}
}
}
}
.drawBehind {
listPointers.forEach {
drawCircle(Color.Red, 50f, it)
}
}.fillMaxSize()
)
}
nuhkoca
05/09/2024, 12:45 PMif (listPointers.size > 2) listPointers.removeAt(0)
if (event.type == PointerEventType.Release) listPointers.clear()
Do you think there is a better approach in order to restrict touch size to any number like 2 and vanish all circles upon release?nuhkoca
05/09/2024, 12:46 PMnuhkoca
06/03/2024, 12:01 AMonDrag = { changes ->
changes
.fastForEach {
touchCoordinates[it.id] = it.position.x
if (it.changedToUp()) {
touchCoordinates.remove(it.id)
}
}
},
However, when I touch the component very rapidly, Compose doesn’t return isConsumed = true
or pressed = false
for the previous one that’s why I am failing to remove the event from my map. Is my code nonsense or is this Compose’s glitch?Rebecca Franks
06/03/2024, 3:01 PMnuhkoca
06/03/2024, 9:35 PMval downPointerCount = event.changes.fastMap {
it.pressed
}.size
val requirementFulfilled = downPointerCount <= numberOfPointers
val canceled = event.changes.fastAny { it.isConsumed }
if (!canceled && requirementFulfilled) {
gestureStarted = true
onDrag(event.changes)
event.changes.fastForEach {
if (it.positionChanged()) {
it.consume()
}
}
}
} while (!canceled && event.changes.fastAny { it.pressed })
Basically, when I rapidly touch the chart with my second finger downPointerCount
is being 2
therefore I can’t invoke onDrag
and failing to remove the previous item when I release my first finger and only keep the second one so I am seeing multiple black dots on the UI 🙂 Looks like I need a else to return a signal to my component in order to remove from map but do you know how can I do that?
if (!canceled && requirementFulfilled) {
...
} else {
// what to return here
}