forked from flutter/flutter
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix interference in fling-scrolling from cross-axis motion
Fixes flutter#120345. The main change here is that when a single-axis DragGestureRecognizer (say, a VerticalDragGestureRecognizer) sees the end of a drag, it now projects the drag's velocity onto its own single axis, and then clamps that. Previously it would clamp the velocity's magnitude as a 2D vector, and then consumers would project *that*, which resulted in clamping too hard when the motion wasn't precisely on-axis. For PanGestureRecognizer, the behavior is unchanged: we continue clamping the velocity as a 2D vector, which is the geometrically nice behavior when we're not trying to focus on a single axis. When I'd first looked at this code, I was concerned that fixing this issue might require a breaking change. But happily I believe it doesn't, for two reasons: * This base class DragGestureRecognizer is effectively sealed (even though Dart doesn't quite yet have that feature), because it has private abstract methods. Dart won't actually stop you extending it, but that seems like a bug in Dart (*); when the class's own method implementations go try to call those methods, they'll produce runtime errors. So it's not possible to subclass it in any useful way from outside the library, which means there are likely no such subclasses anywhere. That means we can freely alter the API between the base class and its subclasses. (*) In fact, it's in the Dart tracker: dart-lang/sdk#25462 * We're also changing the behavior of the `onEnd` callback: previously it would return a DragEndDetails with a two-dimensional velocity, even for a single-axis recognizer, and now it returns a velocity that's always zero in the cross axis. In principle that could be a breaking change; it's a bit odd for a VerticalDragGestureRecognizer to be telling you there was horizontal as well as vertical motion, but someone could nevertheless be depending on that. Fortunately, it turns out that the `onUpdate` callback's behavior already agrees with the view that that is an odd thing that shouldn't happen: it already returns an axis-locked velocity from single-axis recognizers. So the existing `onEnd` behavior is inconsistent with that; and whatever someone might try to do with cross-axis velocity from `onEnd`, it seems like it'd be hard for them to be doing it successfully already when `onUpdate` isn't going along. That makes me hopeful that nobody is depending on that behavior and we can freely clean it up. Also add tests, not only for the changes but for the existing behavior: it turns out that the fancy 2-D clamping, which we keep for PanGestureRecognizer because it's helpful there, wasn't tested at all.
- Loading branch information
Showing
3 changed files
with
156 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters