I am currently trying to implement some functionality that requires me to listen for and react to N simultaneous Press & Release touch events on different UI elements (in a Grid implementation using lazy col/row) in my Jetpack compose UI. I am seeing some behaviour that doesn't seem correct to me.
It appears that every time I press i get the event for that press and any presses before it. The presses accumulate and replay. Then when I release the first release replays all the previous press events -1 each time until the last release which just releases the last press as expected.
Below is a simplified version of my code and the output from the log statements:
Code:
fun MyView(
state: MyState,
onIntent: (Intent) -> Unit = LocalOnIntent.current
) {
Box(
modifier = Modifier
.size(60.dp)
.background(Color(state.color))
.pointerInput(state) {
awaitPointerEventScope {
while (true) {
val event: PointerEvent = awaitPointerEvent()
if (event.type == PointerEventType.Press || event.type == PointerEventType.Release) {
Logger.i { "awaitPointerEvent() ${event.changes.first().id} -:- ${event.type}" }
}
}
}
}
)
}
Output:
First item pressed:
awaitPointerEvent() PointerId(value=1) : Press
Second item pressed:
awaitPointerEvent() PointerId(value=1) : Press
awaitPointerEvent() PointerId(value=2) : Press
Third item pressed:
awaitPointerEvent() PointerId(value=1) : Press
awaitPointerEvent() PointerId(value=2) : Press
awaitPointerEvent() PointerId(value=3) : Press
Third item released:
awaitPointerEvent() PointerId(value=1) : Release
awaitPointerEvent() PointerId(value=2) : Release
awaitPointerEvent() PointerId(value=3) : Release
Second item released:
awaitPointerEvent() PointerId(value=1) : Release
awaitPointerEvent() PointerId(value=2) : Release
First item released:
awaitPointerEvent() PointerId(value=1) : Release
Desired output:
First item pressed:
awaitPointerEvent() PointerId(value=1) : Press
Second item pressed:
awaitPointerEvent() PointerId(value=2) : Press
Third item pressed:
awaitPointerEvent() PointerId(value=3) : Press
Third item released:
awaitPointerEvent() PointerId(value=3) : Release
Second item released:
awaitPointerEvent() PointerId(value=2) : Release
First item released:
awaitPointerEvent() PointerId(value=1) : Release
I did figure out a convoluted workaround whereby I manage all the pressed states from the event.changes list in a map but I really don't like having to do this. It feels like there must be a better way, maybe I have a weird bug, I'm using something wrong or missing something?