Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.swmansion.reanimated.pseudoSelectors

import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewParent
import com.facebook.react.bridge.UIManager
import com.facebook.react.bridge.UIManagerListener
Expand All @@ -25,6 +26,8 @@ class PseudoSelectorManager(

private val gestureDownLeaf = HashMap<View, View>()

private val gestureDownPoint = HashMap<View, FloatArray>()

private val hover = TouchHoverCoordinator()

private val pendingAttaches = LinkedHashMap<String, PendingAttach>()
Expand Down Expand Up @@ -235,6 +238,7 @@ class PseudoSelectorManager(
}
touchHostRefs.remove(host)
gestureDownLeaf.remove(host)
gestureDownPoint.remove(host)
host.setOnTouchListener(null)
}

Expand All @@ -247,6 +251,10 @@ class PseudoSelectorManager(
if (!hover.isGestureSettled(event)) {
onHostDown(host, event)
}
MotionEvent.ACTION_MOVE ->
if (event.findPointerIndex(0) >= 0) {
onHostMove(host, event)
}
MotionEvent.ACTION_POINTER_UP ->
if (event.getPointerId(event.actionIndex) == 0) {
onHostRelease(host)
Expand All @@ -272,13 +280,28 @@ class PseudoSelectorManager(
) {
findTouchedLeaf(host, event)?.let {
gestureDownLeaf[host] = it
gestureDownPoint[host] = floatArrayOf(event.rawX, event.rawY)
fireActiveCallbacksUpTree(it, true)
fireDeepestIfHit(it, event.rawX, event.rawY)
}
hover.onViewTouchDown(host, event)
}

private fun onHostMove(
host: View,
event: MotionEvent,
) {
val down = gestureDownPoint[host] ?: return
val dx = event.rawX - down[0]
val dy = event.rawY - down[1]
val slop = ViewConfiguration.get(host.context).scaledTouchSlop.toFloat()
if (dx * dx + dy * dy > slop * slop) {
onHostRelease(host)
}
}

private fun onHostRelease(host: View) {
gestureDownPoint.remove(host)
val leaf = gestureDownLeaf.remove(host) ?: return
fireActiveCallbacksUpTree(leaf, false)
deepestCallbacks[leaf]?.onSelectorStateChanged(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ - (void)attachMacFocusObservers;
#endif
@end

#if !TARGET_OS_OSX
static const CGFloat kActivePressMovementThreshold = 10.0;
#endif

@implementation REAPseudoSelectorObserver {
__weak REAUIView *_view;
reanimated::PseudoSelector _selector;
Expand All @@ -37,6 +41,10 @@ @implementation REAPseudoSelectorObserver {
NSArray *_notificationObservers;
std::function<void(bool)> _callback;
BOOL _activeTouchCounted;
#if !TARGET_OS_OSX
CGPoint _pressDownLocation;
BOOL _pressDismissed;
#endif
}

#if !TARGET_OS_OSX
Expand Down Expand Up @@ -87,7 +95,7 @@ - (void)attachActiveGestureRecognizerToView:(REAUIView *)view
{
#if !TARGET_OS_OSX
UILongPressGestureRecognizer *recognizer =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchGesture:)];
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleActiveGesture:)];
recognizer.cancelsTouchesInView = NO;
#else
NSPressGestureRecognizer *recognizer =
Expand All @@ -104,7 +112,7 @@ - (void)attachHoverToView:(REAUIView *)view
#if !TARGET_OS_OSX
#if !TARGET_OS_TV
UIHoverGestureRecognizer *recognizer =
[[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchGesture:)];
[[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(handleHoverGesture:)];
recognizer.delegate = self;
[view addGestureRecognizer:recognizer];
_gestureRecognizer = recognizer;
Expand Down Expand Up @@ -261,24 +269,57 @@ - (void)attachFocusObserversWithPredicate:(BOOL (^)(NSNotification *))isOurs

#if !TARGET_OS_OSX

- (void)handleTouchGesture:(UIGestureRecognizer *)recognizer
- (void)handleActiveGesture:(UILongPressGestureRecognizer *)recognizer
{
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
_pressDownLocation = [recognizer locationInView:nil];
_pressDismissed = NO;
_callback(true);
[self retainActiveTouch];
break;
case UIGestureRecognizerStateChanged: {
if (_pressDismissed) {
break;
}
CGPoint point = [recognizer locationInView:nil];
CGFloat dx = point.x - _pressDownLocation.x;
CGFloat dy = point.y - _pressDownLocation.y;
if (dx * dx + dy * dy > kActivePressMovementThreshold * kActivePressMovementThreshold) {
_pressDismissed = YES;
_callback(false);
}
break;
}
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
_callback(false);
if (!_pressDismissed) {
_callback(false);
}
[self releaseActiveTouch];
break;
default:
break;
}
}

- (void)handleHoverGesture:(UIHoverGestureRecognizer *)recognizer
{
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
_callback(true);
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
_callback(false);
break;
default:
break;
}
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (![self isPressSelector]) {
Expand Down
Loading