Skip to content

Commit baf8d71

Browse files
Fix: Scrolling after :hover on iOS (#9791)
#9731 should be merged first. ## Summary There was a bug where after activating :hover on iOS one couldn't scroll anymore. This should fix it. ## Test plan Compile for iOS, go to CSS -> Transitions -> Pseudoselectors -> Hover, tap any exapmle and then try to scroll. --------- Co-authored-by: Mateusz Łopaciński <lop.mateusz.2001@gmail.com>
1 parent 188619e commit baf8d71

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/pseudoSelectors/TouchHoverCoordinator.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ class TouchHoverCoordinator {
6161

6262
/**
6363
* Mirrors CSS hit-testing: turns :hover on for the topmost view at the touch and its registered
64-
* ancestors, off for the rest.
64+
* ancestors, off for the rest. Views that merely overlap the hit branch (which a plain bounds
65+
* test would all activate) stay off, because only the hit branch is hovered. Rooted on the
66+
* touched view's own window so it works inside a Modal/Dialog (a separate window from the Activity).
6567
*/
6668
fun recompute(
6769
sourceView: View,

packages/react-native-reanimated/apple/reanimated/apple/pseudoSelectors/REATouchHoverCoordinator.mm

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ @interface REATouchHoverEntry : NSObject {
1616
@implementation REATouchHoverEntry
1717
@end
1818

19-
/// Passive key-window touch observer. It never leaves `.possible`, so it never claims the gesture
20-
/// or interferes with the per-view `:active` / `:active-deepest` recognizers.
19+
/// Passive key-window touch observer. It only ever transitions to `.failed` (once every finger of a
20+
/// sequence has lifted), so it never claims the gesture or interferes with the per-view `:active` /
21+
/// `:active-deepest` recognizers. Reaching that terminal state each sequence is essential: UIKit only
22+
/// runs `-reset` after a terminal transition, and an observer that stays `.possible` forever is never
23+
/// reset, wedging the key window's gesture environment so a UIScrollView pan can no longer begin.
2124
@interface REAHoverTouchObserver : UIGestureRecognizer
2225
@property (nonatomic, weak) REATouchHoverCoordinator *coordinator;
2326
@end
@@ -37,9 +40,23 @@ - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
3740
{
3841
[self.coordinator observeTouchMoved:touches.anyObject];
3942
}
43+
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
44+
{
45+
[self failIfSequenceEnded:event];
46+
}
4047
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
4148
{
4249
[self.coordinator observeTouchCancelled];
50+
[self failIfSequenceEnded:event];
51+
}
52+
- (void)failIfSequenceEnded:(UIEvent *)event
53+
{
54+
for (UITouch *touch in event.allTouches) {
55+
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) {
56+
return;
57+
}
58+
}
59+
self.state = UIGestureRecognizerStateFailed;
4360
}
4461
@end
4562

0 commit comments

Comments
 (0)