Sitelet https://github.com/flutter/flutter/issues/181752
Skip to content

Proposal - Missing dedicated "Rubber Band" physics in BouncingScrollPhysics causes low iOS fidelity #181752

Description

@MTtankkeo

Currently, BouncingScrollPhysics in Flutter uses a single SpringDescription for both momentum scrolling (flings) and the overscroll recovery (snap-back/rubber band effect).

This design forces a compromise:

  • If we tune the spring for a natural scroll feel, the snap-back becomes too loose and "floaty" compared to native iOS.
  • If we tune it for a snappy return, the scrolling becomes too stiff.

As a result, Flutter's iOS scroll feel lacks the characteristic "heavy and snappy" rubber band effect found in UIScrollView, creating an "uncanny valley" effect for users.

Video

online-video-cutter.com.mp4

Describe the solution

Native iOS behaves as if it uses a different physical property when snapping back from an overscroll. Flutter should implement a dedicated spring simulation for this specific phase.

I have analyzed the motion curves of native iOS and found that separating the spring logic significantly improves fidelity.

Proposed Logic:

  1. Keep the existing spring for standard scrolling to maintain smoothness.
  2. Apply a specific "Rubber Band Spring" when the scroll position is out of bounds and the gesture ends.
  3. Empirically tuned values for this spring: mass: 1.0, stiffness: 1e5 * lambda^2, damping: 100001 * lambda.

Note

The constants were specially tuned to achieve exponential damping for the spring.

Additional context

I have measured and compared the scroll position over time between:

  1. Native iOS (UIScrollView)
  2. Current Flutter
  3. New Flutter implementation
Image

As shown in the graph, the current Flutter implementation (Cyan) exhibits a significantly slower recovery compared to native iOS. It lacks the initial 'snap' (stiffness) and takes considerably longer to settle (~0.81s) compared to the native duration (~0.63s), leading to the perceived "floaty" behavior.

In contrast, the new implementation (Brown) closely aligns with the native curve (Blue) in trajectory.

I have a PR ready with this fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: proposalA detailed proposal for a change to Flutterf: scrollingViewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.platform-iosiOS applications specificallyteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions