Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix ScrollView centerContent losing taps and causing jitter on iOS (#…
…47591) Summary: The React Native `<ScrollView>` has a peculiar `centerContent` prop. It solves a common need — keeping the image "centered" while it's not fully zoomed in (but then allowing full panning after it's sufficiently zoomed in). This prop sort of works but it has a few wonky behaviors: - If you start tapping immediately after pinch (and don't stop), the taps will not be recognized until a second after you stop tapping. I suspect this is because the existing `centerContent` implementation hijacks the `contentOffset` setter, but the calling UIKit code _does not know_ it's being hijacked, and so the calling UIKit code _thinks_ it needs to do a momentum animation. This (invisible) momentum animation causes the scroll view to keep eating the tap touches. - While you're zooming in, once you cross the threshold where `contentOffset` hijacking stops adjusting values, there will be a sudden visual jump during the pinch. This is because the "real" `contentOffset` tracks the accumulated translation from the pinch gesture, and once it gets taken into account with no "correction", the new offset snaps into place. - While not sufficiently pinched in, the vertical axis is completely rigid. It does not have the natural rubber banding. The solution to all of these issues is described [here](https://petersteinberger.com/blog/2013/how-to-center-uiscrollview/). Instead of hijacking `contentOffset`, it is more reliable to track zooming, child view, and frame changes, and adjust `contentInsets` instead. This solves all three issues: - UIKit isn't confused by the content offset changing from under it so it doesn't mistrigger a faux momentum animation. - There is no sudden jump because it's the insets that are being adjusted. - Rubber banding just works. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [IOS] [FIXED] - Fixed centerContent losing taps and causing jitter Pull Request resolved: #47591 Test Plan: I'm extracting this from [a patch we're applying to Bluesky](https://github.com/bluesky-social/social-app/blob/2ef697fe3d7dec198544ed6834553f33b95790b3/patches/react-native%2B0.74.1.patch). I'll be honest — I have not tested this in isolation, and it likely requires some testing to get merged in. I do not, unfortuntately, have the capacity to do it myself so this is more of a "throw over the wall" kind of patch. Maybe it will be helpful to somebody else. I've tested these in our real open source app (bluesky-social/social-app#6298). You can reproduce it in any of the lightboxes in the feed or the profile. ### Before the fix Observe the failing tap gestures, sudden jump while pinching, lack of rubber banding. https://github.com/user-attachments/assets/c9883201-c9f0-4782-9b80-8e0a9f77c47c ### After the fix Observe the natural iOS behavior. https://github.com/user-attachments/assets/c025e1df-6963-40ba-9e28-d48bfa5e631d Unfortunately I do not have the capacity to verify this fix in other scenarios outside of our app. Reviewed By: sammy-SC Differential Revision: D66093472 Pulled By: javache fbshipit-source-id: 064f0415b8093ff55cb51bdebab2a46ee97f8fa9
- Loading branch information