-
-
Notifications
You must be signed in to change notification settings - Fork 525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(Android,Fabric): pressable on Screen
loses focus on pointer movement
#2292
Conversation
…@alduzy/pressable-fabric-fix
…on/react-native-screens into @kkafar/fabric-pressables
270134b
to
867284c
Compare
I'd still wait for @kkafar to come back and elaborate why he wanted to leave the |
## Description This PR applies modifications to a previous fix: #2169 for fabric only, which has stopped working since RN `0.75`. In RN `0.74` the `adopt` in `RNSScreenComponentDescriptior.h` was once called without `stateData` but with children and we could then check if the `ScreenStackHeaderConfig` is present among them and make adjustments based on it. When working on #2292 it became clear that the fix does not work anymore. Now the `adopt` is called either with no children and no `stateData` or with both. The solution is to move the code to `appendChild` in `RNSScreenShadowNode.cpp` so we can perform the adjustments as soon as the children append. ## Changes - moved code from `adopt` in `RNSScreenComponentDescriptior.h` to newly added `appendChild` override in `RNSScreenShadowNode.cpp` ## Screenshots / GIFs ### Before https://github.com/user-attachments/assets/6b76864b-58bb-4c6e-9f5b-a01bb0c88d2a ### After https://github.com/user-attachments/assets/98931e77-3877-4f67-8b28-f49d2e0f42ff ## Test code and steps to reproduce - Use `TestHeader` to test this change ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <[email protected]>
@WoLewicki I've left |
Screen
loses focus on pointer movement
So it was only for libs like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this fixes the issue with pressables on screen (but not in header), thus I'm for merging it.
The issue with pressables in header will be handled separately.
@WoLewicki Exactly, but right now we should prioritise making it work & defer integration with reanimated. |
Please release these changes. |
I'm facing the same issue! |
…ement (software-mansion#2292) ## Description > [!important] This PR aims to fix only pressables on screen components. This PR does not fix similar pressable issue with pressables in native header. That interaction will be fixed separately. Pressable elements work just fine until there's a gesture involved. On sensitive physical devices even a little movement during the press is treated as a gesture. When the `Pressable` element detects a gesture it calls [onResponderMove](https://github.com/facebook/react-native/blob/82795715aefba07ae9d79278ce3fd4d2e9a928f2/packages/react-native/Libraries/Pressability/Pressability.js#L484) which then checks wether the gesture happened within the element or went outside by comparing the touch coordinates with coordinates of the element using `_isTouchWithinResponderRegion`. The `responderRegion` is obtained from `_responderID` and happens to have unexpected values when the native header is present. It tuns out that the Y origin is slightly off. After some further investigation and comparison of coordinates it turned out that the height of the android status bar is not well calculated in various scenarios: <table> <td> `statusBarHidden: true` </td> <td> `statusBarTranslucent: true` </td> <td> `statusBarTranslucent: false` </td> </tr> <tr> <td> ![Screenshot_1723212300](https://github.com/user-attachments/assets/57e2f4a3-b002-4ca3-9519-45cfece860c4) </td> <td> ![Screenshot_1723212331](https://github.com/user-attachments/assets/bd46c8d1-8813-4fae-a8a9-0326193371d2) </td> <td> ![Screenshot_1723212382](https://github.com/user-attachments/assets/c7373437-524d-4a0f-951e-ce2689a4fe5c) </td> </tr> </table> The `calculateHeaderHeight` used for calculating the header and statusBar height seems to be the problem. Luckily, we don't have to calculate it by ourselves anymore, because the correct `t` value is provided in the `onLayout` function of the `Screen`. Thus we can get rid of the custom function. Another issue found: after navigating to another screen the offset is off again (exactly by 2x). It's caused by changes introduced in [this PR](software-mansion#2169), which was supposed to prevent content jumps, but doesn't work since RN `0.75` sadly. ![Screenshot_1723220034](https://github.com/user-attachments/assets/b0908c23-4667-4ccf-8e5e-5e7e11bca316) I found out that `FrameOriginCorrection` is not being unset when dimensions from JVM are received, while the `FrameHeightCorrection` is. After adding the missing unset for `FrameOriginCorrection` I rolled back to the commit with the mentioned PR merged and RN `0.74` and I can confirm it works. Fixes software-mansion#1975 ## Changes - removed `calculateHeaderHeight` function - added unset for `FrameOriginCorrection` when dimensions from JVM are received - added `Test1975.tsx` repro - moved code responsible for determining header height during the very first render from component descriptor's `adopt` method to shadow node `appendChild`. ## Test code and steps to reproduce `TestHeader`, `Test1975` ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes --------- Co-authored-by: alduzy <[email protected]> Co-authored-by: Alex Duży <[email protected]>
The onPress event does not work for me (Android), but only in a specific situation: Inside a scrollview inside a drawer's content, AND scrolled down more than a few pixels. But onPressIn does work. I'm assuming this has the same root cause. And I'm on the latest beta version (4.0.0-beta.9) so I'm guessing this won't be fixed anytime soon. |
@WKampel, if you mind providing a reproduction we might be quicker to handle this, thanks! |
…ement (#2292) > [!important] This PR aims to fix only pressables on screen components. This PR does not fix similar pressable issue with pressables in native header. That interaction will be fixed separately. Pressable elements work just fine until there's a gesture involved. On sensitive physical devices even a little movement during the press is treated as a gesture. When the `Pressable` element detects a gesture it calls [onResponderMove](https://github.com/facebook/react-native/blob/82795715aefba07ae9d79278ce3fd4d2e9a928f2/packages/react-native/Libraries/Pressability/Pressability.js#L484) which then checks wether the gesture happened within the element or went outside by comparing the touch coordinates with coordinates of the element using `_isTouchWithinResponderRegion`. The `responderRegion` is obtained from `_responderID` and happens to have unexpected values when the native header is present. It tuns out that the Y origin is slightly off. After some further investigation and comparison of coordinates it turned out that the height of the android status bar is not well calculated in various scenarios: <table> <td> `statusBarHidden: true` </td> <td> `statusBarTranslucent: true` </td> <td> `statusBarTranslucent: false` </td> </tr> <tr> <td> ![Screenshot_1723212300](https://github.com/user-attachments/assets/57e2f4a3-b002-4ca3-9519-45cfece860c4) </td> <td> ![Screenshot_1723212331](https://github.com/user-attachments/assets/bd46c8d1-8813-4fae-a8a9-0326193371d2) </td> <td> ![Screenshot_1723212382](https://github.com/user-attachments/assets/c7373437-524d-4a0f-951e-ce2689a4fe5c) </td> </tr> </table> The `calculateHeaderHeight` used for calculating the header and statusBar height seems to be the problem. Luckily, we don't have to calculate it by ourselves anymore, because the correct `t` value is provided in the `onLayout` function of the `Screen`. Thus we can get rid of the custom function. Another issue found: after navigating to another screen the offset is off again (exactly by 2x). It's caused by changes introduced in [this PR](#2169), which was supposed to prevent content jumps, but doesn't work since RN `0.75` sadly. ![Screenshot_1723220034](https://github.com/user-attachments/assets/b0908c23-4667-4ccf-8e5e-5e7e11bca316) I found out that `FrameOriginCorrection` is not being unset when dimensions from JVM are received, while the `FrameHeightCorrection` is. After adding the missing unset for `FrameOriginCorrection` I rolled back to the commit with the mentioned PR merged and RN `0.74` and I can confirm it works. Fixes #1975 - removed `calculateHeaderHeight` function - added unset for `FrameOriginCorrection` when dimensions from JVM are received - added `Test1975.tsx` repro - moved code responsible for determining header height during the very first render from component descriptor's `adopt` method to shadow node `appendChild`. `TestHeader`, `Test1975` - [x] Included code example that can be used to test this change - [x] Ensured that CI passes --------- Co-authored-by: alduzy <[email protected]> Co-authored-by: Alex Duży <[email protected]> (cherry picked from commit 34c1ba8)
Description
Important
This PR aims to fix only pressables on screen components. This PR does not fix similar pressable issue with pressables in native header. That interaction will be fixed separately.
Pressable elements work just fine until there's a gesture involved. On sensitive physical devices even a little movement during the press is treated as a gesture.
When the
Pressable
element detects a gesture it calls onResponderMove which then checks wether the gesture happened within the element or went outside by comparing the touch coordinates with coordinates of the element using_isTouchWithinResponderRegion
.The
responderRegion
is obtained from_responderID
and happens to have unexpected values when the native header is present. It tuns out that the Y origin is slightly off. After some further investigation and comparison of coordinates it turned out that the height of the android status bar is not well calculated in various scenarios:statusBarHidden: true
statusBarTranslucent: true
statusBarTranslucent: false
The
calculateHeaderHeight
used for calculating the header and statusBar height seems to be the problem. Luckily, we don't have to calculate it by ourselves anymore, because the correctt
value is provided in theonLayout
function of theScreen
. Thus we can get rid of the custom function.Another issue found: after navigating to another screen the offset is off again (exactly by 2x). It's caused by changes introduced in this PR, which was supposed to prevent content jumps, but doesn't work since RN
0.75
sadly.I found out that
FrameOriginCorrection
is not being unset when dimensions from JVM are received, while theFrameHeightCorrection
is. After adding the missing unset forFrameOriginCorrection
I rolled back to the commit with the mentioned PR merged and RN0.74
and I can confirm it works.Fixes #1975
Changes
calculateHeaderHeight
functionFrameOriginCorrection
when dimensions from JVM are receivedTest1975.tsx
reproadopt
method to shadow nodeappendChild
.Test code and steps to reproduce
TestHeader
,Test1975
Checklist