Skip to content

Commit

Permalink
Update to 2.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tsapeta committed Oct 4, 2022
1 parent d08e79d commit d7fa30f
Show file tree
Hide file tree
Showing 25 changed files with 244 additions and 145 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -10,7 +10,7 @@ Package-specific changes not released in any SDK will be added here just before
- Updated `@stripe/stripe-react-native` from `0.13.1` to `0.18.1` on iOS. ([#19055](https://github.com/expo/expo/pull/19055) by [@tsapeta](https://github.com/tsapeta))
- Updated `@shopify/flash-list` from `1.1.0` to `1.3.0`. ([#19317](https://github.com/expo/expo/pull/19317) by [@kudo](https://github.com/kudo))
- Updated `react-native-webview` from `11.23.0` to `11.23.1`. ([#19375](https://github.com/expo/expo/pull/19375) by [@aleqsio](https://github.com/aleqsio))
- Updated `react-native-gesture-handler` from `2.5.0` to `2.6.2`. ([#19362](https://github.com/expo/expo/pull/19362) by [@tsapeta](https://github.com/tsapeta))
- Updated `react-native-gesture-handler` from `2.5.0` to `2.7.0`. ([#19362](https://github.com/expo/expo/pull/19362) by [@tsapeta](https://github.com/tsapeta))

### 🛠 Breaking changes

Expand Down
Expand Up @@ -63,19 +63,19 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
}
}

override fun onHandle(event: MotionEvent) {
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
val state = state
if (state == STATE_UNDETERMINED) {
startFling(event)
startFling(sourceEvent)
}
if (state == STATE_BEGAN) {
tryEndFling(event)
if (event.pointerCount > maxNumberOfPointersSimultaneously) {
maxNumberOfPointersSimultaneously = event.pointerCount
tryEndFling(sourceEvent)
if (sourceEvent.pointerCount > maxNumberOfPointersSimultaneously) {
maxNumberOfPointersSimultaneously = sourceEvent.pointerCount
}
val action = event.actionMasked
val action = sourceEvent.actionMasked
if (action == MotionEvent.ACTION_UP) {
endFling(event)
endFling(sourceEvent)
}
}
}
Expand Down
Expand Up @@ -4,6 +4,7 @@ import host.exp.expoview.BuildConfig
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.graphics.PointF
import android.graphics.Rect
import android.view.MotionEvent
import android.view.MotionEvent.PointerCoords
Expand Down Expand Up @@ -326,7 +327,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
while handling event: $event
""".trimIndent(), e) {}

fun handle(origEvent: MotionEvent) {
fun handle(transformedEvent: MotionEvent, sourceEvent: MotionEvent) {
if (!isEnabled
|| state == STATE_CANCELLED
|| state == STATE_FAILED
Expand All @@ -336,20 +337,20 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
}

// a workaround for https://github.com/software-mansion/react-native-gesture-handler/issues/1188
val event = if (BuildConfig.DEBUG) {
adaptEvent(origEvent)
val (adaptedTransformedEvent, adaptedSourceEvent) = if (BuildConfig.DEBUG) {
arrayOf(adaptEvent(transformedEvent), adaptEvent(sourceEvent))
} else {
try {
adaptEvent(origEvent)
arrayOf(adaptEvent(transformedEvent), adaptEvent(sourceEvent))
} catch (e: AdaptEventException) {
fail()
return
}
}

x = event.x
y = event.y
numberOfPointers = event.pointerCount
x = adaptedTransformedEvent.x
y = adaptedTransformedEvent.y
numberOfPointers = adaptedTransformedEvent.pointerCount
isWithinBounds = isWithinBounds(view, x, y)
if (shouldCancelWhenOutside && !isWithinBounds) {
if (state == STATE_ACTIVE) {
Expand All @@ -359,13 +360,16 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
}
return
}
lastAbsolutePositionX = GestureUtils.getLastPointerX(event, true)
lastAbsolutePositionY = GestureUtils.getLastPointerY(event, true)
lastEventOffsetX = event.rawX - event.x
lastEventOffsetY = event.rawY - event.y
onHandle(event)
if (event != origEvent) {
event.recycle()
lastAbsolutePositionX = GestureUtils.getLastPointerX(adaptedTransformedEvent, true)
lastAbsolutePositionY = GestureUtils.getLastPointerY(adaptedTransformedEvent, true)
lastEventOffsetX = adaptedTransformedEvent.rawX - adaptedTransformedEvent.x
lastEventOffsetY = adaptedTransformedEvent.rawY - adaptedTransformedEvent.y
onHandle(adaptedTransformedEvent, adaptedSourceEvent)
if (adaptedTransformedEvent != transformedEvent) {
adaptedTransformedEvent.recycle()
}
if (adaptedSourceEvent != sourceEvent) {
adaptedSourceEvent.recycle()
}
}

Expand Down Expand Up @@ -586,11 +590,11 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
var top = 0f
var right = view!!.width.toFloat()
var bottom = view.height.toFloat()
if (hitSlop != null) {
val padLeft = hitSlop!![HIT_SLOP_LEFT_IDX]
val padTop = hitSlop!![HIT_SLOP_TOP_IDX]
val padRight = hitSlop!![HIT_SLOP_RIGHT_IDX]
val padBottom = hitSlop!![HIT_SLOP_BOTTOM_IDX]
hitSlop?.let { hitSlop ->
val padLeft = hitSlop[HIT_SLOP_LEFT_IDX]
val padTop = hitSlop[HIT_SLOP_TOP_IDX]
val padRight = hitSlop[HIT_SLOP_RIGHT_IDX]
val padBottom = hitSlop[HIT_SLOP_BOTTOM_IDX]
if (hitSlopSet(padLeft)) {
left -= padLeft
}
Expand All @@ -603,8 +607,8 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
if (hitSlopSet(padBottom)) {
bottom += padBottom
}
val width = hitSlop!![HIT_SLOP_WIDTH_IDX]
val height = hitSlop!![HIT_SLOP_HEIGHT_IDX]
val width = hitSlop[HIT_SLOP_WIDTH_IDX]
val height = hitSlop[HIT_SLOP_HEIGHT_IDX]
if (hitSlopSet(width)) {
if (!hitSlopSet(padLeft)) {
left = right - width
Expand Down Expand Up @@ -660,13 +664,29 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
// if the handler is waiting for failure of other one)
open fun resetProgress() {}

protected open fun onHandle(event: MotionEvent) {
protected open fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
moveToState(STATE_FAILED)
}

protected open fun onStateChange(newState: Int, previousState: Int) {}
protected open fun onReset() {}
protected open fun onCancel() {}

/**
* Transforms a point in the coordinate space of the wrapperView (GestureHandlerRootView) to
* coordinate space of the view the gesture is attached to.
*
* If the gesture handler is not currently attached to a view, it will return (NaN, NaN).
*
* This method modifies and transforms the received point.
*/
protected fun transformPoint(point: PointF): PointF {
return orchestrator?.transformPointToViewCoords(this.view, point) ?: run {
point.x = Float.NaN
point.y = Float.NaN
point
}
}
fun reset() {
view = null
orchestrator = null
Expand All @@ -690,14 +710,14 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
}

val lastRelativePositionX: Float
get() = lastAbsolutePositionX - lastEventOffsetX
get() = lastAbsolutePositionX
val lastRelativePositionY: Float
get() = lastAbsolutePositionY - lastEventOffsetY
get() = lastAbsolutePositionY

val lastPositionInWindowX: Float
get() = lastAbsolutePositionX - windowOffset[0]
get() = lastAbsolutePositionX + lastEventOffsetX - windowOffset[0]
val lastPositionInWindowY: Float
get() = lastAbsolutePositionY - windowOffset[1]
get() = lastAbsolutePositionY + lastEventOffsetY - windowOffset[1]

companion object {
const val STATE_UNDETERMINED = 0
Expand Down
Expand Up @@ -242,26 +242,17 @@ class GestureHandlerOrchestrator(
}
}

private fun deliverEventToGestureHandler(handler: GestureHandler<*>, event: MotionEvent) {
private fun deliverEventToGestureHandler(handler: GestureHandler<*>, sourceEvent: MotionEvent) {
if (!isViewAttachedUnderWrapper(handler.view)) {
handler.cancel()
return
}
if (!handler.wantEvents()) {
return
}
val action = event.actionMasked
val coords = tempCoords
extractCoordsForView(handler.view, event, coords)
val oldX = event.x
val oldY = event.y
// TODO: we may consider scaling events if necessary using MotionEvent.transform
// for now the events are only offset to the top left corner of the view but if
// view or any ot the parents is scaled the other pointers position will not reflect
// their actual place in the view. On the other hand not scaling seems like a better
// approach when we want to use pointer coordinates to calculate velocity or distance
// for pinch so I don't know yet if we should transform or not...
event.setLocation(coords[0], coords[1])

val action = sourceEvent.actionMasked
val event = transformEventToViewCoords(handler.view, MotionEvent.obtain(sourceEvent))

// Touch events are sent before the handler itself has a chance to process them,
// mainly because `onTouchesUp` shoul be send befor gesture finishes. This means that
Expand All @@ -277,7 +268,7 @@ class GestureHandlerOrchestrator(

if (!handler.isAwaiting || action != MotionEvent.ACTION_MOVE) {
val isFirstEvent = handler.state == 0
handler.handle(event)
handler.handle(event, sourceEvent)
if (handler.isActive) {
// After handler is done waiting for other one to fail its progress should be
// reset, otherwise there may be a visible jump in values sent by the handler.
Expand Down Expand Up @@ -305,7 +296,7 @@ class GestureHandlerOrchestrator(
}
}

event.setLocation(oldX, oldY)
event.recycle()
}

/**
Expand All @@ -329,19 +320,75 @@ class GestureHandlerOrchestrator(
return parent === wrapperView
}

private fun extractCoordsForView(view: View?, event: MotionEvent, outputCoords: FloatArray) {
if (view === wrapperView) {
outputCoords[0] = event.x
outputCoords[1] = event.y
return
/**
* Transforms an event in the coordinates of wrapperView into the coordinate space of the received view.
*
* This modifies and returns the same event as it receives
*
* @param view - view to which coordinate space the event should be transformed
* @param event - event to transform
*/
fun transformEventToViewCoords(view: View?, event: MotionEvent): MotionEvent {
if (view == null) {
return event
}
require(!(view == null || view.parent !is ViewGroup)) { "Parent is null? View is no longer in the tree" }
val parent = view.parent as ViewGroup
extractCoordsForView(parent, event, outputCoords)
val childPoint = tempPoint
transformTouchPointToViewCoords(outputCoords[0], outputCoords[1], parent, view, childPoint)
outputCoords[0] = childPoint.x
outputCoords[1] = childPoint.y

val parent = view.parent as? ViewGroup
// Events are passed down to the orchestrator by the wrapperView, so they are already in the
// relevant coordinate space. We want to stop traversing the tree when we reach it.
if (parent != wrapperView) {
transformEventToViewCoords(parent, event)
}

if (parent != null) {
val localX = event.x + parent.scrollX - view.left
val localY = event.y + parent.scrollY - view.top
event.setLocation(localX, localY)
}

if (!view.matrix.isIdentity) {
view.matrix.invert(inverseMatrix)
event.transform(inverseMatrix)
}

return event
}

/**
* Transforms a point in the coordinates of wrapperView into the coordinate space of the received view.
*
* This modifies and returns the same point as it receives
*
* @param view - view to which coordinate space the point should be transformed
* @param point - point to transform
*/
fun transformPointToViewCoords(view: View?, point: PointF): PointF {
if (view == null) {
return point
}

val parent = view.parent as? ViewGroup
// Events are passed down to the orchestrator by the wrapperView, so they are already in the
// relevant coordinate space. We want to stop traversing the tree when we reach it.
if (parent != wrapperView) {
transformPointToViewCoords(parent, point)
}

if (parent != null) {
point.x += parent.scrollX - view.left
point.y += parent.scrollY - view.top
}

if (!view.matrix.isIdentity) {
view.matrix.invert(inverseMatrix)
tempCoords[0] = point.x
tempCoords[1] = point.y
inverseMatrix.mapPoints(tempCoords)
point.x = tempCoords[0]
point.y = tempCoords[1]
}

return point
}

private fun addAwaitingHandler(handler: GestureHandler<*>) {
Expand Down Expand Up @@ -451,7 +498,7 @@ class GestureHandlerOrchestrator(
val child = viewConfigHelper.getChildInDrawingOrderAtIndex(viewGroup, i)
if (canReceiveEvents(child)) {
val childPoint = tempPoint
transformTouchPointToViewCoords(coords[0], coords[1], viewGroup, child, childPoint)
transformPointToChildViewCoords(coords[0], coords[1], viewGroup, child, childPoint)
val restoreX = coords[0]
val restoreY = coords[1]
coords[0] = childPoint.x
Expand Down Expand Up @@ -564,7 +611,7 @@ class GestureHandlerOrchestrator(
return isLeafOrTransparent && isTransformedTouchPointInView(coords[0], coords[1], view)
}

private fun transformTouchPointToViewCoords(
private fun transformPointToChildViewCoords(
x: Float,
y: Float,
parent: ViewGroup,
Expand Down
Expand Up @@ -4,14 +4,13 @@ import android.view.MotionEvent

object GestureUtils {
fun getLastPointerX(event: MotionEvent, averageTouches: Boolean): Float {
val offset = event.rawX - event.x
val excludeIndex = if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) event.actionIndex else -1
return if (averageTouches) {
var sum = 0f
var count = 0
for (i in 0 until event.pointerCount) {
if (i != excludeIndex) {
sum += event.getX(i) + offset
sum += event.getX(i)
count++
}
}
Expand All @@ -21,19 +20,18 @@ object GestureUtils {
if (lastPointerIdx == excludeIndex) {
lastPointerIdx--
}
event.getX(lastPointerIdx) + offset
event.getX(lastPointerIdx)
}
}

fun getLastPointerY(event: MotionEvent, averageTouches: Boolean): Float {
val offset = event.rawY - event.y
val excludeIndex = if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) event.actionIndex else -1
return if (averageTouches) {
var sum = 0f
var count = 0
for (i in 0 until event.pointerCount) {
if (i != excludeIndex) {
sum += event.getY(i) + offset
sum += event.getY(i)
count++
}
}
Expand All @@ -43,7 +41,7 @@ object GestureUtils {
if (lastPointerIdx == excludeIndex) {
lastPointerIdx -= 1
}
event.getY(lastPointerIdx) + offset
event.getY(lastPointerIdx)
}
}
}

0 comments on commit d7fa30f

Please sign in to comment.