Pablichjenkov
02/28/2023, 5:17 AMvar pointerEnabled by remember(someState) { mutableStateOf(true) }
Box(
modifier = Modifier
.fillMaxSize()
.pointerInputModifierSwitcher(pointerEnabled, topBarState) {
detectDragGestures(
onDragStart = { offset ->
if (offset.x > 50) {
pointerEnabled = false
}
startX = offset.x
},
...
}
)
// where pointerInput is added/removed from the modifiers depending on `pointerEnabled`
fun Modifier.pointerInputModifierSwitcher(
enable: Boolean,
key1: Any?,
block: suspend PointerInputScope.() -> Unit
): Modifier {
return if (enable) {
this.pointerInput(key1, block)
} else {
this
}
}
Now, If the drag gesture starts with offset.x > 50, I don’t want the Box to consume it but the HorizontalPager to do so. I set pointerEnabled to false so it triggers recomposition and the pointerInput is removed in the next recomposition.
The problem is that once the drag gesture starts with offset.x > 50, when I cancel/remove the pointerInput modifier from the Box, the events are not propagated to the Pager until the drag gesture finishes. It is until the next drag gesture that the Pager gets to handle the touch events.
What is the way to switch/divert the touch events to the parent (in this case the Pager), in the same gesture that is taking place.
In the classic system there used to be an interceptTouch in the ViewGroup class that you could override, or also returning false from the onTouchEvent() would let the parent know you are not interested in handling the touch stream. Any similar in compose?Pablichjenkov
02/28/2023, 6:11 AMnestedScroll(nestedScrollConnection)
but the problem is, it is intended to be added as a modifier on the parent of the LayoutNode in question, in this case the Pager. But if I add the nestedScroll()
modifier in one of the Pager's children, the callbacks don't get called. So it doesn't help me.ephemient
03/05/2023, 5:19 AMephemient
03/05/2023, 5:21 AMpointerInput
, by using awaitPointerEvent(pass = PointerEventPass.Initial)
and altering or consuming the event before continuingPablichjenkov
03/07/2023, 2:36 AMPablichjenkov
03/07/2023, 2:47 AM.pointerInput(key1, block) {
detectDragGestures(...)
}
and it works ok, in the sense that I always get the events stream and can do what I want. But, when the user starts dragging in the green area, I haven’t found a way to stop consuming the event stream and let the parent consume it instead. If I remove the pointer input from MyDraggableScreen after detecting the first touch in the green area, the parent does not get the event stream.
The system waits until the current drag gesture finishes, then the next one is dispatched in the parent.Pablichjenkov
03/07/2023, 2:47 AMawaitPointerEvent
, I let you know it it makes the trickPablichjenkov
03/07/2023, 5:59 AM.pointerInput(topBarState) {
forEachGesture {
awaitPointerEventScope {
val eventDown = awaitFirstDown(requireUnconsumed = true)
if (eventDown.position.x < PredictiveArea) {
eventDown.consume()
startX.value = eventDown.position.x
do {
val event: PointerEvent = awaitPointerEvent(PointerEventPass.Main)
event.changes.forEach {
it.consume()
}
event.changes.lastOrNull()?.let {
deltaX.value = it.position.x -startX.value
}
} while (event.changes.any { it.pressed })
if (deltaX.value > PredictiveArea) {
stackState.handleBackPress()
}
startX.value = Float.MAX_VALUE
deltaX.value = 0f
}
}
}
}