Commit 36c38731 authored by Adam Barth's avatar Adam Barth

Merge pull request #831 from abarth/scroll_tolerance

Improve tolerance for ending scroll animations
parents 11da9b02 95fc9810
......@@ -10,6 +10,12 @@ import 'package:newton/newton.dart';
const double _kSecondsPerMillisecond = 1000.0;
const double _kScrollDrag = 0.025;
// TODO(abarth): These values won't work well if there's a scale transform.
final Tolerance _kDefaultScrollTolerance = new Tolerance(
velocity: 1.0 / (0.050 * ui.window.devicePixelRatio), // logical pixels per second
distance: 1.0 / ui.window.devicePixelRatio // logical pixels
);
/// An interface for controlling the behavior of scrollable widgets
abstract class ScrollBehavior {
/// Called when a drag gesture ends. Returns a simulation that
......@@ -102,29 +108,19 @@ class UnboundedBehavior extends ExtentScrollBehavior {
}
}
Simulation _createFlingScrollSimulation(double position, double velocity, double minScrollOffset, double maxScrollOffset) {
Simulation _createFlingScrollSimulation(double position, double velocity, double minScrollOffset, double maxScrollOffset, Tolerance tolerance) {
double startVelocity = velocity * _kSecondsPerMillisecond;
// Assume that we're rendering at atleast 15 FPS. Stop when we're
// scrolling less than one logical pixel per frame. We're essentially
// normalizing by the devicePixelRatio so that the threshold has the
// same effect independent of the device's pixel density.
double endVelocity = 15.0 * ui.window.devicePixelRatio;
// Similar to endVelocity. Stop scrolling when we're this close to
// destiniation scroll offset.
double endDistance = 0.5 * ui.window.devicePixelRatio;
SpringDescription spring = new SpringDescription.withDampingRatio(mass: 1.0, springConstant: 170.0, ratio: 1.1);
ScrollSimulation simulation =
new ScrollSimulation(position, startVelocity, minScrollOffset, maxScrollOffset, spring, _kScrollDrag)
..tolerance = new Tolerance(velocity: endVelocity.abs(), distance: endDistance);
..tolerance = tolerance ?? _kDefaultScrollTolerance;
return simulation;
}
Simulation _createSnapScrollSimulation(double startOffset, double endOffset, double velocity) {
double startVelocity = velocity * _kSecondsPerMillisecond;
double endVelocity = 15.0 * ui.window.devicePixelRatio * velocity.sign;
double endVelocity = velocity.sign * _kDefaultScrollTolerance.velocity;
return new FrictionSimulation.through(startOffset, endOffset, startVelocity, endVelocity);
}
......@@ -133,8 +129,8 @@ class OverscrollBehavior extends BoundedBehavior {
OverscrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 })
: super(contentExtent: contentExtent, containerExtent: containerExtent);
Simulation createFlingScrollSimulation(double position, double velocity) {
return _createFlingScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset);
Simulation createFlingScrollSimulation(double position, double velocity, { Tolerance tolerance }) {
return _createFlingScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset, tolerance);
}
Simulation createSnapScrollSimulation(double startOffset, double endOffset, double velocity) {
......@@ -162,9 +158,9 @@ class OverscrollBehavior extends BoundedBehavior {
class OverscrollWhenScrollableBehavior extends OverscrollBehavior {
bool get isScrollable => contentExtent > containerExtent;
Simulation createFlingScrollSimulation(double position, double velocity) {
Simulation createFlingScrollSimulation(double position, double velocity, { Tolerance tolerance }) {
if (isScrollable || position < minScrollOffset || position > maxScrollOffset)
return super.createFlingScrollSimulation(position, velocity);
return super.createFlingScrollSimulation(position, velocity, tolerance: tolerance);
return null;
}
......
......@@ -57,10 +57,10 @@ class SpringSimulation extends Simulation {
double dx(double time) => _solution.dx(time);
@override
bool isDone(double time) =>
_nearEqual(x(time), _endPosition, this.tolerance.distance) &&
_nearZero(dx(time), this.tolerance.velocity);
bool isDone(double time) {
return _nearZero(_solution.x(time), tolerance.distance) &&
_nearZero(_solution.dx(time), tolerance.velocity);
}
}
/// A SpringSimulation where the value of x() is guaranteed to have exactly the
......@@ -69,16 +69,5 @@ class ScrollSpringSimulation extends SpringSimulation {
ScrollSpringSimulation(SpringDescription desc, double start, double end, double velocity)
: super(desc, start, end, velocity);
bool _isDone(double position, double velocity) {
return _nearEqual(position, _endPosition, tolerance.distance) && _nearZero(velocity, tolerance.velocity);
}
@override
double x(double time) {
double xAtTime = super.x(time);
return _isDone(xAtTime, dx(time)) ? _endPosition : xAtTime;
}
@override
bool isDone(double time) => _isDone(x(time), dx(time));
double x(double time) => isDone(time) ? _endPosition : super.x(time);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment