Skip to content
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 ScrollView centerContent losing taps and causing jitter on iOS #47591

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Nov 13, 2024

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. 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:

[IOS] [FIXED] - Fixed centerContent losing taps and causing jitter

Test Plan:

I'm extracting this from a patch we're applying to Bluesky. 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.

merged.mov

After the fix

Observe the natural iOS behavior.

IMG_8963.MOV

Unfortunately I do not have the capacity to verify this fix in other scenarios outside of our app.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 13, 2024
Not sure if needed, but don't want to regress from facebook#24817
{
if (_scrollView.centerContent &&
!CGSizeEqualToSize(self.contentSize, CGSizeZero) &&
!CGSizeEqualToSize(self.bounds.size, CGSizeZero)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about these defensive checks. Added them to avoid losing the fix from #24817 but I don't have a repro case and I'm not a UIKit expert.

@gaearon
Copy link
Collaborator Author

gaearon commented Nov 17, 2024

cc @cipolleschi @NickGerleman @sammy-SC figured one of you might have context on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants