[multi-shade] Fix multi touch bug.
Dragging down with one finger, adding a second finger, then removing the original finger was crashing because the pointer index for the saved off pointer ID is missing. This CL fixes it by seamlessly moving over to the next pointer when the original pointer is lifted. Bug: 274159734 Test: manually verified that (a) the crash doesn't happen and (b) the shaded continues to drag down smoothly without a "jump". Test: I considered a unit test but decided against it because it was going to be very hard to set up MotionEvent instances for different pointers based on the obtain API. Change-Id: Idbc534660b947ce450aa819e1322eb934978de79
This commit is contained in:
@@ -182,6 +182,26 @@ constructor(
|
||||
interactionState = null
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_POINTER_UP -> {
|
||||
val removedPointerId = event.getPointerId(event.actionIndex)
|
||||
if (removedPointerId == interactionState?.pointerId && event.pointerCount > 1) {
|
||||
// We removed the original pointer but there must be another pointer because the
|
||||
// gesture is still ongoing. Let's switch to that pointer.
|
||||
interactionState =
|
||||
event.firstUnremovedPointerId(removedPointerId)?.let { replacementPointerId
|
||||
->
|
||||
interactionState?.copy(
|
||||
pointerId = replacementPointerId,
|
||||
// We want to update the currentY of our state so that the
|
||||
// transition to the next pointer doesn't report a big jump between
|
||||
// the Y coordinate of the removed pointer and the Y coordinate of
|
||||
// the replacement pointer.
|
||||
currentY = event.getY(replacementPointerId),
|
||||
)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL -> {
|
||||
if (isDraggingShade()) {
|
||||
// Our drag gesture was canceled by the system. This happens primarily in one of
|
||||
@@ -219,4 +239,17 @@ constructor(
|
||||
private fun isDraggingShade(): Boolean {
|
||||
return interactionState?.isDraggingShade ?: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first pointer that is not [removedPointerId] or `null`, if there is
|
||||
* no other pointer.
|
||||
*/
|
||||
private fun MotionEvent.firstUnremovedPointerId(removedPointerId: Int): Int? {
|
||||
return (0 until pointerCount)
|
||||
.firstOrNull { pointerIndex ->
|
||||
val pointerId = getPointerId(pointerIndex)
|
||||
pointerId != removedPointerId
|
||||
}
|
||||
?.let { pointerIndex -> getPointerId(pointerIndex) }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user