Skip to content

Commit

Permalink
Add example for Pressability with Native Driver in RNTester (facebook…
Browse files Browse the repository at this point in the history
…#45413)

Summary:
Pull Request resolved: facebook#45413

## Changes
Add an example in RNTester to test that pressability with NativeDrivers works properly.

## Context
The pressability handling is a bit peculiar.
We have to handle 3 main behaviors:
* `PressIn` -> `PressOut` => triggers the `onPress`
* `PressIn` -> move inside the rectangle -> `PressOut` => triggers the `onPress`
* `PressIn` -> move outside the rectangle -> `PressOut` => cancel `onPress`.

For the first case, we detect whether the press happens inside a component in the Native layer only. And everything works.

When a move is involved, we:
1. Detect the initial press in the Native layer
2. We move the coursor and we delegate the detection of whether we are inside of a rect or not to the JS layer
3. The JS layer asks the C++ layer about the layout and decide whether we are in case 2 (move but still inside the rect) or in case 3 (move but outside the rect).

The problem is that with `nativeDriver` and animations, the C++ layer doesn't know about where the receiver view actually is.
This results in issues like the one shown by [facebook#36504](facebook#36504), where the onMove is not handled correctly.

## Solution
The solution is to keep detecting whether we are in the receiver view or not in the Native layer and pass the receiver view position and size back to JS so that the JS layer don't have to jump to C++ to make this decision.

We decided to pass the frame information because the JS layer is adding some padding and configurations to the final rectangle and we don't want to lose those configurations.

## Changelog
[General][Added] - Add example in RNTester to show that pressability works properly with NativeDrivers

Reviewed By: sammy-SC

Differential Revision: D58182480
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Jul 15, 2024
1 parent 3c7e307 commit 01bc97a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/rn-tester/js/examples/Animated/AnimatedIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import MovingBoxExample from './MovingBoxExample';
import RotatingImagesExample from './RotatingImagesExample';
import TransformBounceExample from './TransformBounceExample';
import TransformStylesExample from './TransformStylesExample';
import PressabilityWithNativeDrivers from './PressabilityWithNativeDrivers';

export default ({
framework: 'React',
Expand All @@ -45,5 +46,6 @@ export default ({
LoopingExample,
ContinuousInteractionsExample,
CombineExample,
PressabilityWithNativeDrivers,
],
}: RNTesterModule);
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import type {RNTesterModuleExample} from '../../types/RNTesterTypes';

import * as React from 'react';
import {Animated, Button, Text, View} from 'react-native';

const componentList: number[] = Array.from({length: 100}, (_, i) => i + 1);

function PressableWithNativeDriver() {
const currScroll = React.useRef(new Animated.Value(0)).current;
const [count, setCount] = React.useState(0);

return (
<View style={{flex: 1}}>
<Animated.View
style={{
position: 'absolute',
zIndex: 2,
width: '100%',
transform: [{translateY: currScroll}],
}}>
<Button
title={`Press count : ${count}`}
onPress={() => {
console.log('pressed');
setCount(count + 1);
}}
/>
</Animated.View>
<Animated.FlatList
style={{width: '100%', height: '100%', position: 'absolute', zIndex: 1}}
data={componentList}
renderItem={({index}) => (
<Text
style={{
backgroundColor: 'white',
height: 28,
}}>
{index}
</Text>
)}
keyExtractor={item => item.toString()}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: currScroll,
},
},
},
],
{useNativeDriver: true},
)}
/>
</View>
);
}

export default ({
title: 'Pressability With Native Driver',
name: 'pressabilityWithNativeDrivers',
description: 'Pressabile animated with Native Drivers',
render: () => <PressableWithNativeDriver />,
}: RNTesterModuleExample);

0 comments on commit 01bc97a

Please sign in to comment.