Repository navigation
Commit 34f5e48
authored
[iOS] Add hover callbacks to Touchable (#4397)
## Description
The Apple side of `onHoverIn`/`onHoverOut`, covering iOS, tvOS and
macOS. Mirrors the Android state machine, with the pointer sampled from
`UIHoverGestureRecognizer` on iOS, the `NSTrackingArea` on macOS, and
the touch stream during a press.
- `RNGHButtonPressEventDelegate` becomes `RNGHButtonEventDelegate` now
that it carries more than presses.
- The touch-derived path is gated on a press-start latch. Without it a
plain pencil tap on an iPad that doesn't report pencil hover would open
a hover on touch-up that nothing could ever close.
- The pointer type is latched for the duration of a hover — a pencil's
`zOffset` collapses to zero as it approaches contact, which would
otherwise make the hover-out claim a different type than the hover-in.
- tvOS drives hover from focus rather than a pointer, so there's no
sample to report; the payload falls back to the button's centre.
## Test plan
Not covered by the JS tests. Needs an iPad with a trackpad or a
hover-capable pencil, a Mac, and a tvOS device for the focus path.
<details>
<summary>Example code</summary>
```tsx
import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import {
GestureHandlerRootView,
Touchable,
} from 'react-native-gesture-handler';
export default function Example() {
const [log, setLog] = useState<string[]>([]);
const callbacks = (source: string) => ({
onHoverIn: () => setLog((l) => [`${source} onHoverIn`, ...l]),
onHoverOut: () => setLog((l) => [`${source} onHoverOut`, ...l]),
onPressIn: () => setLog((l) => [`${source} onPressIn`, ...l]),
onPressOut: () => setLog((l) => [`${source} onPressOut`, ...l]),
});
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.row}>
<Touchable style={styles.box} {...callbacks('Touchable')}>
<Text style={styles.text}>Touchable</Text>
</Touchable>
<Pressable style={styles.box} {...callbacks('Pressable')}>
<Text style={styles.text}>Pressable</Text>
</Pressable>
</View>
{log.slice(0, 12).map((entry, i) => (
<Text key={i}>{entry}</Text>
))}
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24 },
row: { flexDirection: 'row', gap: 24, marginBottom: 24 },
box: {
width: 120,
height: 120,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#6941C6',
},
text: { color: 'white' },
});
```
</details>1 parent 78cec50 commit 34f5e48
3 files changed
Lines changed: 221 additions & 21 deletions
File tree
- packages/react-native-gesture-handler/apple
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
20 | | - | |
21 | | - | |
| 22 | + | |
| 23 | + | |
22 | 24 | | |
23 | | - | |
| 25 | + | |
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| |||
70 | 72 | | |
71 | 73 | | |
72 | 74 | | |
73 | | - | |
| 75 | + | |
74 | 76 | | |
75 | 77 | | |
76 | 78 | | |
| |||
0 commit comments