From f167efba498c087e43ebc276dedf69a2335da15b Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Fri, 14 Oct 2016 20:09:19 -0700 Subject: [PATCH] Tweaked scroll simulation for iOS platform (#6334) --- packages/flutter/lib/physics.dart | 1 - .../lib/src/widgets/scroll_behavior.dart | 40 +++++-------- .../scroll_simulation.dart | 59 +++++++++++++++---- packages/flutter/lib/widgets.dart | 1 + .../flutter/test/physics/newton_test.dart | 38 ++++++++++-- 5 files changed, 98 insertions(+), 41 deletions(-) rename packages/flutter/lib/src/{physics => widgets}/scroll_simulation.dart (61%) diff --git a/packages/flutter/lib/physics.dart b/packages/flutter/lib/physics.dart index 78e7cd1b9a..3120779092 100644 --- a/packages/flutter/lib/physics.dart +++ b/packages/flutter/lib/physics.dart @@ -11,7 +11,6 @@ library physics; export 'src/physics/clamped_simulation.dart'; export 'src/physics/friction_simulation.dart'; export 'src/physics/gravity_simulation.dart'; -export 'src/physics/scroll_simulation.dart'; export 'src/physics/simulation_group.dart'; export 'src/physics/simulation.dart'; export 'src/physics/spring_simulation.dart'; diff --git a/packages/flutter/lib/src/widgets/scroll_behavior.dart b/packages/flutter/lib/src/widgets/scroll_behavior.dart index 5f36a08804..cbab8ad1c4 100644 --- a/packages/flutter/lib/src/widgets/scroll_behavior.dart +++ b/packages/flutter/lib/src/widgets/scroll_behavior.dart @@ -8,16 +8,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/physics.dart'; import 'package:meta/meta.dart'; +import 'scroll_simulation.dart'; + export 'package:flutter/foundation.dart' show TargetPlatform; -const double _kScrollDragMountainView = 0.025; -const double _kScrollDragCupertino = 0.125; -final SpringDescription _kScrollSpring = new SpringDescription.withDampingRatio(mass: 0.5, springConstant: 100.0, ratio: 1.1); - -Simulation _createScrollSimulation(double position, double velocity, double minScrollOffset, double maxScrollOffset, double scrollDrag) { - return new ScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset, _kScrollSpring, scrollDrag); -} - Simulation _createSnapScrollSimulation(double startOffset, double endOffset, double startVelocity, double endVelocity) { return new FrictionSimulation.through(startOffset, endOffset, startVelocity, endVelocity); } @@ -69,20 +63,6 @@ abstract class ScrollBehavior { /// Whether this scroll behavior currently permits scrolling. bool get isScrollable => true; - /// The scroll drag constant to use for physics simulations created by this - /// ScrollBehavior. - double get scrollDrag { - assert(platform != null); - switch (platform) { - case TargetPlatform.android: - case TargetPlatform.fuchsia: - return _kScrollDragMountainView; - case TargetPlatform.iOS: - return _kScrollDragCupertino; - } - return null; - } - @override String toString() { List description = []; @@ -220,8 +200,12 @@ class UnboundedBehavior extends ExtentScrollBehavior { @override Simulation createScrollSimulation(double position, double velocity) { - return new BoundedFrictionSimulation( - scrollDrag, position, velocity, double.NEGATIVE_INFINITY, double.INFINITY + return new ScrollSimulation( + position: position, + velocity: velocity, + leadingExtent: double.NEGATIVE_INFINITY, + trailingExtent: double.INFINITY, + platform: platform, ); } @@ -259,7 +243,13 @@ class OverscrollBehavior extends BoundedBehavior { @override Simulation createScrollSimulation(double position, double velocity) { - return _createScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset, scrollDrag); + return new ScrollSimulation( + position: position, + velocity: velocity, + leadingExtent: minScrollOffset, + trailingExtent: maxScrollOffset, + platform: platform, + ); } @override diff --git a/packages/flutter/lib/src/physics/scroll_simulation.dart b/packages/flutter/lib/src/widgets/scroll_simulation.dart similarity index 61% rename from packages/flutter/lib/src/physics/scroll_simulation.dart rename to packages/flutter/lib/src/widgets/scroll_simulation.dart index 5d9fd975c5..e082bc2b09 100644 --- a/packages/flutter/lib/src/physics/scroll_simulation.dart +++ b/packages/flutter/lib/src/widgets/scroll_simulation.dart @@ -2,10 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'friction_simulation.dart'; -import 'simulation_group.dart'; -import 'simulation.dart'; -import 'spring_simulation.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/physics.dart'; + +final SpringDescription _kScrollSpring = new SpringDescription.withDampingRatio(mass: 0.5, springConstant: 100.0, ratio: 1.1); + +class _MountainViewSimulation extends FrictionSimulation { + static const double drag = 0.025; + _MountainViewSimulation({ double position, double velocity }) + : super(drag, position, velocity); +} + +class _CupertinoSimulation extends FrictionSimulation { + static const double drag = 0.135; + _CupertinoSimulation({ double position, double velocity }) + : super(drag, position, velocity * 0.91); +} /// Composite simulation for scrollable interfaces. /// @@ -26,13 +38,22 @@ class ScrollSimulation extends SimulationGroup { /// consistent with the other arguments. /// /// The final argument is the coefficient of friction, which is unitless. - ScrollSimulation( + ScrollSimulation({ double position, double velocity, - this._leadingExtent, - this._trailingExtent, - this._spring, - this._drag) { + double leadingExtent, + double trailingExtent, + SpringDescription spring, + double drag, + TargetPlatform platform, + }) : _leadingExtent = leadingExtent, + _trailingExtent = trailingExtent, + _spring = spring ?? _kScrollSpring, + _drag = drag, + _platform = platform { + assert(_leadingExtent != null); + assert(_trailingExtent != null); + assert(_spring != null); _chooseSimulation(position, velocity, 0.0); } @@ -40,6 +61,7 @@ class ScrollSimulation extends SimulationGroup { final double _trailingExtent; final SpringDescription _spring; final double _drag; + final TargetPlatform _platform; bool _isSpringing = false; Simulation _currentSimulation; @@ -76,7 +98,24 @@ class ScrollSimulation extends SimulationGroup { } if (_currentSimulation == null) { - _currentSimulation = new FrictionSimulation(_drag, position, velocity); + switch (_platform) { + case TargetPlatform.android: + case TargetPlatform.fuchsia: + _currentSimulation = new _MountainViewSimulation( + position: position, + velocity: velocity + ); + break; + case TargetPlatform.iOS: + _currentSimulation = new _CupertinoSimulation( + position: position, + velocity: velocity, + ); + break; + } + // No platform specified + _currentSimulation ??= new FrictionSimulation(_drag, position, velocity); + return true; } diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index 9c498bb8e0..ef2a284127 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -48,6 +48,7 @@ export 'src/widgets/raw_keyboard_listener.dart'; export 'src/widgets/routes.dart'; export 'src/widgets/scroll_behavior.dart'; export 'src/widgets/scroll_configuration.dart'; +export 'src/widgets/scroll_simulation.dart'; export 'src/widgets/scrollable.dart'; export 'src/widgets/scrollable_grid.dart'; export 'src/widgets/scrollable_list.dart'; diff --git a/packages/flutter/test/physics/newton_test.dart b/packages/flutter/test/physics/newton_test.dart index 96aec9a66b..5b7aa56669 100644 --- a/packages/flutter/test/physics/newton_test.dart +++ b/packages/flutter/test/physics/newton_test.dart @@ -5,6 +5,7 @@ import 'package:test/test.dart'; import 'package:flutter/physics.dart'; +import 'package:flutter/widgets.dart'; void main() { test('test_friction', () { @@ -191,13 +192,27 @@ void main() { SpringDescription spring = new SpringDescription.withDampingRatio( mass: 1.0, springConstant: 50.0, ratio: 0.5); - ScrollSimulation scroll = new ScrollSimulation(100.0, 800.0, 0.0, 300.0, spring, 0.3); + ScrollSimulation scroll = new ScrollSimulation( + position: 100.0, + velocity: 800.0, + leadingExtent: 0.0, + trailingExtent: 300.0, + spring: spring, + drag: 0.3 + ); scroll.tolerance = const Tolerance(velocity: 0.5, distance: 0.1); expect(scroll.isDone(0.0), false); expect(scroll.isDone(0.5), false); // switch from friction to spring expect(scroll.isDone(3.5), true); - ScrollSimulation scroll2 = new ScrollSimulation(100.0, -800.0, 0.0, 300.0, spring, 0.3); + ScrollSimulation scroll2 = new ScrollSimulation( + position: 100.0, + velocity: -800.0, + leadingExtent: 0.0, + trailingExtent: 300.0, + spring: spring, + drag: 0.3 + ); scroll2.tolerance = const Tolerance(velocity: 0.5, distance: 0.1); expect(scroll2.isDone(0.0), false); expect(scroll2.isDone(0.5), false); // switch from friction to spring @@ -208,8 +223,14 @@ void main() { SpringDescription spring = new SpringDescription.withDampingRatio( mass: 1.0, springConstant: 50.0, ratio: 0.5); - ScrollSimulation scroll = - new ScrollSimulation(100.0, 400.0, 0.0, double.INFINITY, spring, 0.3); + ScrollSimulation scroll = new ScrollSimulation( + position: 100.0, + velocity: 400.0, + leadingExtent: 0.0, + trailingExtent: double.INFINITY, + spring: spring, + drag: 0.3, + ); scroll.tolerance = const Tolerance(velocity: 1.0); expect(scroll.isDone(0.0), false); @@ -232,7 +253,14 @@ void main() { test('over/under scroll spring', () { SpringDescription spring = new SpringDescription.withDampingRatio(mass: 1.0, springConstant: 170.0, ratio: 1.1); - ScrollSimulation scroll = new ScrollSimulation(500.0, -7500.0, 0.0, 1000.0, spring, 0.025); + ScrollSimulation scroll = new ScrollSimulation( + position: 500.0, + velocity: -7500.0, + leadingExtent: 0.0, + trailingExtent: 1000.0, + spring: spring, + drag: 0.025, + ); scroll.tolerance = new Tolerance(velocity: 45.0, distance: 1.5); expect(scroll.isDone(0.0), false);