diff --git a/examples/flutter_gallery/lib/demo/grid_list_demo.dart b/examples/flutter_gallery/lib/demo/grid_list_demo.dart index f5357442f1c..98dde46da2c 100644 --- a/examples/flutter_gallery/lib/demo/grid_list_demo.dart +++ b/examples/flutter_gallery/lib/demo/grid_list_demo.dart @@ -78,29 +78,29 @@ class _GridPhotoViewerState extends State with SingleTickerProv }); } - void _handleOnScaleStart(Point focalPoint) { + void _handleOnScaleStart(ScaleStartDetails details) { setState(() { _lastScale = 1.0; - _lastFocalPoint = focalPoint; + _lastFocalPoint = details.focalPoint; // The fling animation stops if an input gesture starts. _controller.stop(); }); } - void _handleOnScaleUpdate(double scale, Point focalPoint) { + void _handleOnScaleUpdate(ScaleUpdateDetails details) { setState(() { - _scale = (_scale + (scale - _lastScale)).clamp(1.0, 3.0); - _lastScale = scale; - _focalPoint = _clampFocalPoint(_focalPoint + (_lastFocalPoint - focalPoint)); - _lastFocalPoint = focalPoint; + _scale = (_scale + (details.scale - _lastScale)).clamp(1.0, 3.0); + _lastScale = details.scale; + _focalPoint = _clampFocalPoint(_focalPoint + (_lastFocalPoint - details.focalPoint)); + _lastFocalPoint = details.focalPoint; }); } - void _handleOnScaleEnd(Velocity flingVelocity) { - final double magnitude = flingVelocity.pixelsPerSecond.distance; + void _handleOnScaleEnd(ScaleEndDetails details) { + final double magnitude = details.velocity.pixelsPerSecond.distance; if (magnitude < _kMinFlingVelocity) return; - final Offset direction = flingVelocity.pixelsPerSecond / magnitude; + final Offset direction = details.velocity.pixelsPerSecond / magnitude; final RenderBox box = context.findRenderObject(); final double distance = (Point.origin & box.size).shortestSide; _flingAnimation = new Tween( diff --git a/examples/layers/widgets/gestures.dart b/examples/layers/widgets/gestures.dart index e7bf9b12f53..f06e970c9a7 100644 --- a/examples/layers/widgets/gestures.dart +++ b/examples/layers/widgets/gestures.dart @@ -79,21 +79,21 @@ class _GestureDemoState extends State { bool _doubleTapEnabled = true; bool _longPressEnabled = true; - void _handleScaleStart(Point focalPoint) { + void _handleScaleStart(ScaleStartDetails details) { setState(() { - _startingFocalPoint = focalPoint; + _startingFocalPoint = details.focalPoint; _previousOffset = _offset; _previousZoom = _zoom; }); } - void _handleScaleUpdate(double scale, Point focalPoint) { + void _handleScaleUpdate(ScaleUpdateDetails details) { setState(() { - _zoom = (_previousZoom * scale); + _zoom = (_previousZoom * details.scale); // Ensure that item under the focal point stays in the same place despite zooming Offset normalizedOffset = (_startingFocalPoint.toOffset() - _previousOffset) / _previousZoom; - _offset = focalPoint.toOffset() - normalizedOffset * _zoom; + _offset = details.focalPoint.toOffset() - normalizedOffset * _zoom; }); } diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index 623f672937f..fc0faaf5842 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -27,16 +27,63 @@ enum ScaleState { started, } +/// Details for [GestureScaleStartCallback]. +class ScaleStartDetails { + /// Creates details for [GestureScaleStartCallback]. + /// + /// The [focalPoint] argument must not be null. + ScaleStartDetails({ this.focalPoint: Point.origin }) { + assert(focalPoint != null); + } + + /// The initial focal point of the pointers in contact with the screen. + /// Reported in global coordinates. + final Point focalPoint; +} + +/// Details for [GestureScaleUpdateCallback]. +class ScaleUpdateDetails { + /// Creates details for [GestureScaleUpdateCallback]. + /// + /// The [focalPoint] and [scale] arguments must not be null. The [scale] + /// argument must be greater than or equal to zero. + ScaleUpdateDetails({ this.focalPoint: Point.origin, this.scale: 1.0 }) { + assert(focalPoint != null); + assert(scale != null && scale >= 0.0); + } + + /// The focal point of the pointers in contact with the screen. Reported in + /// global coordinates. + final Point focalPoint; + + /// The scale implied by the pointers in contact with the screen. A value + /// greater than or equal to zero. + final double scale; +} + +/// Details for [GestureScaleEndCallback]. +class ScaleEndDetails { + /// Creates details for [GestureScaleEndCallback]. + /// + /// The [velocity] argument must not be null. + ScaleEndDetails({ this.velocity: Velocity.zero }) { + assert(velocity != null); + } + + /// The velocity of the last pointer to be lifted off of the screen. + final Velocity velocity; +} + /// Signature for when the pointers in contact with the screen have established /// a focal point and initial scale of 1.0. -typedef void GestureScaleStartCallback(Point focalPoint); +typedef void GestureScaleStartCallback(ScaleStartDetails details); /// Signature for when the pointers in contact with the screen have indicated a /// new focal point and/or scale. -typedef void GestureScaleUpdateCallback(double scale, Point focalPoint); +typedef void GestureScaleUpdateCallback(ScaleUpdateDetails details); /// Signature for when the pointers are no longer in contact with the screen. -typedef void GestureScaleEndCallback(Velocity flingVelocity); +typedef void GestureScaleEndCallback(ScaleEndDetails details); bool _isFlingGesture(Velocity velocity) { assert(velocity != null); @@ -133,9 +180,9 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { final Offset pixelsPerSecond = velocity.pixelsPerSecond; if (pixelsPerSecond.distanceSquared > kMaxFlingVelocity * kMaxFlingVelocity) velocity = new Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * kMaxFlingVelocity); - onEnd(velocity); + onEnd(new ScaleEndDetails(velocity: velocity)); } else { - onEnd(Velocity.zero); + onEnd(new ScaleEndDetails(velocity: Velocity.zero)); } } _state = ScaleState.accepted; @@ -153,11 +200,11 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { if (_state == ScaleState.accepted && !configChanged) { _state = ScaleState.started; if (onStart != null) - onStart(focalPoint); + onStart(new ScaleStartDetails(focalPoint: focalPoint)); } if (_state == ScaleState.started && onUpdate != null) - onUpdate(_scaleFactor, focalPoint); + onUpdate(new ScaleUpdateDetails(scale: _scaleFactor, focalPoint: focalPoint)); } @override diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 86bc4cc464b..76b8b70212f 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -26,6 +26,9 @@ export 'package:flutter/gestures.dart' show GestureScaleStartCallback, GestureScaleUpdateCallback, GestureScaleEndCallback, + ScaleStartDetails, + ScaleUpdateDetails, + ScaleEndDetails, TapDownDetails, TapUpDetails, Velocity; diff --git a/packages/flutter/test/gestures/scale_test.dart b/packages/flutter/test/gestures/scale_test.dart index 7fb93818d9a..c6be89ea6ca 100644 --- a/packages/flutter/test/gestures/scale_test.dart +++ b/packages/flutter/test/gestures/scale_test.dart @@ -16,19 +16,19 @@ void main() { bool didStartScale = false; Point updatedFocalPoint; - scale.onStart = (Point focalPoint) { + scale.onStart = (ScaleStartDetails details) { didStartScale = true; - updatedFocalPoint = focalPoint; + updatedFocalPoint = details.focalPoint; }; double updatedScale; - scale.onUpdate = (double scale, Point focalPoint) { - updatedScale = scale; - updatedFocalPoint = focalPoint; + scale.onUpdate = (ScaleUpdateDetails details) { + updatedScale = details.scale; + updatedFocalPoint = details.focalPoint; }; bool didEndScale = false; - scale.onEnd = (Velocity flingVelocity) { + scale.onEnd = (ScaleEndDetails details) { didEndScale = true; };