Adding horizontal and vertical scale parameter to ScaleUpdateDetails. (#27752)
This commit is contained in:
committed by
Michael Goderbauer
parent
ed4e3da360
commit
2cbd050f92
@@ -49,30 +49,67 @@ class ScaleStartDetails {
|
||||
class ScaleUpdateDetails {
|
||||
/// Creates details for [GestureScaleUpdateCallback].
|
||||
///
|
||||
/// The [focalPoint], [scale], [rotation] arguments must not be null. The [scale]
|
||||
/// The [focalPoint], [scale], [horizontalScale], [verticalScale], [rotation]
|
||||
/// arguments must not be null. The [scale], [horizontalScale], and [verticalScale]
|
||||
/// argument must be greater than or equal to zero.
|
||||
ScaleUpdateDetails({
|
||||
this.focalPoint = Offset.zero,
|
||||
this.scale = 1.0,
|
||||
this.horizontalScale = 1.0,
|
||||
this.verticalScale = 1.0,
|
||||
this.rotation = 0.0,
|
||||
}) : assert(focalPoint != null),
|
||||
assert(scale != null && scale >= 0.0),
|
||||
assert(horizontalScale != null && horizontalScale >= 0.0),
|
||||
assert(verticalScale != null && verticalScale >= 0.0),
|
||||
assert(rotation != null);
|
||||
|
||||
/// The focal point of the pointers in contact with the screen. Reported in
|
||||
/// global coordinates.
|
||||
/// The focal point of the pointers in contact with the screen.
|
||||
///
|
||||
/// Reported in global coordinates.
|
||||
final Offset focalPoint;
|
||||
|
||||
/// The scale implied by the pointers in contact with the screen. A value
|
||||
/// greater than or equal to zero.
|
||||
/// The scale implied by the average distance between the pointers in contact
|
||||
/// with the screen.
|
||||
///
|
||||
/// This value must be greater than or equal to zero.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [horizontalScale], which is the scale along the horizontal axis.
|
||||
/// * [verticalScale], which is the scale along the vertical axis.
|
||||
final double scale;
|
||||
|
||||
/// The scale implied by the average distance along the horizontal axis
|
||||
/// between the pointers in contact with the screen.
|
||||
///
|
||||
/// This value must be greater than or equal to zero.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [scale], which is the general scale implied by the pointers.
|
||||
/// * [verticalScale], which is the scale along the vertical axis.
|
||||
final double horizontalScale;
|
||||
|
||||
/// The scale implied by the average distance along the vertical axis
|
||||
/// between the pointers in contact with the screen.
|
||||
///
|
||||
/// This value must be greater than or equal to zero.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [scale], which is the general scale implied by the pointers.
|
||||
/// * [horizontalScale], which is the scale along the horizontal axis.
|
||||
final double verticalScale;
|
||||
|
||||
/// The angle implied by the first two pointers to enter in contact with
|
||||
/// the screen. Expressed in radians.
|
||||
/// the screen.
|
||||
///
|
||||
/// Expressed in radians.
|
||||
final double rotation;
|
||||
|
||||
@override
|
||||
String toString() => 'ScaleUpdateDetails(focalPoint: $focalPoint, scale: $scale, rotation: $rotation)';
|
||||
String toString() => 'ScaleUpdateDetails(focalPoint: $focalPoint, scale: $scale, horizontalScale: $horizontalScale, verticalScale: $verticalScale, rotation: $rotation)';
|
||||
}
|
||||
|
||||
/// Details for [GestureScaleEndCallback].
|
||||
@@ -165,6 +202,10 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
Offset _currentFocalPoint;
|
||||
double _initialSpan;
|
||||
double _currentSpan;
|
||||
double _initialHorizontalSpan;
|
||||
double _currentHorizontalSpan;
|
||||
double _initialVerticalSpan;
|
||||
double _currentVerticalSpan;
|
||||
_LineBetweenPointers _initialLine;
|
||||
_LineBetweenPointers _currentLine;
|
||||
Map<int, Offset> _pointerLocations;
|
||||
@@ -173,6 +214,10 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
|
||||
double get _scaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0;
|
||||
|
||||
double get _horizontalScaleFactor => _initialHorizontalSpan > 0.0 ? _currentHorizontalSpan / _initialHorizontalSpan : 1.0;
|
||||
|
||||
double get _verticalScaleFactor => _initialVerticalSpan > 0.0 ? _currentVerticalSpan / _initialVerticalSpan : 1.0;
|
||||
|
||||
double _computeRotationFactor() {
|
||||
if (_initialLine == null || _currentLine == null) {
|
||||
return 0.0;
|
||||
@@ -201,6 +246,10 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
_state = _ScaleState.possible;
|
||||
_initialSpan = 0.0;
|
||||
_currentSpan = 0.0;
|
||||
_initialHorizontalSpan = 0.0;
|
||||
_currentHorizontalSpan = 0.0;
|
||||
_initialVerticalSpan = 0.0;
|
||||
_currentVerticalSpan = 0.0;
|
||||
_pointerLocations = <int, Offset>{};
|
||||
_pointerQueue = <int>[];
|
||||
}
|
||||
@@ -246,11 +295,20 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
focalPoint += _pointerLocations[pointer];
|
||||
_currentFocalPoint = count > 0 ? focalPoint / count.toDouble() : Offset.zero;
|
||||
|
||||
// Span is the average deviation from focal point
|
||||
// Span is the average deviation from focal point. Horizontal and vertical
|
||||
// spans are the average deviations from the focal point's horizontal and
|
||||
// vertical coordinates, respectively.
|
||||
double totalDeviation = 0.0;
|
||||
for (int pointer in _pointerLocations.keys)
|
||||
double totalHorizontalDeviation = 0.0;
|
||||
double totalVerticalDeviation = 0.0;
|
||||
for (int pointer in _pointerLocations.keys) {
|
||||
totalDeviation += (_currentFocalPoint - _pointerLocations[pointer]).distance;
|
||||
totalHorizontalDeviation += (_currentFocalPoint.dx - _pointerLocations[pointer].dx).abs();
|
||||
totalVerticalDeviation += (_currentFocalPoint.dy - _pointerLocations[pointer].dy).abs();
|
||||
}
|
||||
_currentSpan = count > 0 ? totalDeviation / count : 0.0;
|
||||
_currentHorizontalSpan = count > 0 ? totalHorizontalDeviation / count : 0.0;
|
||||
_currentVerticalSpan = count > 0 ? totalVerticalDeviation / count : 0.0;
|
||||
}
|
||||
|
||||
/// Updates [_initialLine] and [_currentLine] accordingly to the situation of
|
||||
@@ -269,7 +327,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
pointerStartId: _pointerQueue[0],
|
||||
pointerStartLocation: _pointerLocations[_pointerQueue[0]],
|
||||
pointerEndId: _pointerQueue[1],
|
||||
pointerEndLocation: _pointerLocations[ _pointerQueue[1]]
|
||||
pointerEndLocation: _pointerLocations[_pointerQueue[1]]
|
||||
);
|
||||
} else {
|
||||
/// A new rotation process is on the way, set the [_initialLine]
|
||||
@@ -277,7 +335,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
pointerStartId: _pointerQueue[0],
|
||||
pointerStartLocation: _pointerLocations[_pointerQueue[0]],
|
||||
pointerEndId: _pointerQueue[1],
|
||||
pointerEndLocation: _pointerLocations[ _pointerQueue[1]]
|
||||
pointerEndLocation: _pointerLocations[_pointerQueue[1]]
|
||||
);
|
||||
_currentLine = null;
|
||||
}
|
||||
@@ -287,6 +345,8 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
_initialFocalPoint = _currentFocalPoint;
|
||||
_initialSpan = _currentSpan;
|
||||
_initialLine = _currentLine;
|
||||
_initialHorizontalSpan = _currentHorizontalSpan;
|
||||
_initialVerticalSpan = _currentVerticalSpan;
|
||||
if (_state == _ScaleState.started) {
|
||||
if (onEnd != null) {
|
||||
final VelocityTracker tracker = _velocityTrackers[pointer];
|
||||
@@ -327,7 +387,15 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
}
|
||||
|
||||
if (_state == _ScaleState.started && onUpdate != null)
|
||||
invokeCallback<void>('onUpdate', () => onUpdate(ScaleUpdateDetails(scale: _scaleFactor, focalPoint: _currentFocalPoint, rotation: _computeRotationFactor())));
|
||||
invokeCallback<void>('onUpdate', () {
|
||||
onUpdate(ScaleUpdateDetails(
|
||||
scale: _scaleFactor,
|
||||
horizontalScale: _horizontalScaleFactor,
|
||||
verticalScale: _verticalScaleFactor,
|
||||
focalPoint: _currentFocalPoint,
|
||||
rotation: _computeRotationFactor(),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
void _dispatchOnStartCallbackIfNeeded() {
|
||||
|
||||
@@ -24,8 +24,12 @@ void main() {
|
||||
};
|
||||
|
||||
double updatedScale;
|
||||
double updatedHorizontalScale;
|
||||
double updatedVerticalScale;
|
||||
scale.onUpdate = (ScaleUpdateDetails details) {
|
||||
updatedScale = details.scale;
|
||||
updatedHorizontalScale = details.horizontalScale;
|
||||
updatedVerticalScale = details.verticalScale;
|
||||
updatedFocalPoint = details.focalPoint;
|
||||
};
|
||||
|
||||
@@ -91,18 +95,35 @@ void main() {
|
||||
expect(updatedFocalPoint, const Offset(10.0, 20.0));
|
||||
updatedFocalPoint = null;
|
||||
expect(updatedScale, 2.0);
|
||||
expect(updatedHorizontalScale, 2.0);
|
||||
expect(updatedVerticalScale, 2.0);
|
||||
updatedScale = null;
|
||||
updatedHorizontalScale = null;
|
||||
updatedVerticalScale = null;
|
||||
expect(didEndScale, isFalse);
|
||||
expect(didTap, isFalse);
|
||||
|
||||
// Zoom out
|
||||
tester.route(pointer2.move(const Offset(15.0, 25.0)));
|
||||
expect(updatedFocalPoint, const Offset(17.5, 27.5));
|
||||
updatedFocalPoint = null;
|
||||
expect(updatedScale, 0.5);
|
||||
updatedScale = null;
|
||||
expect(updatedHorizontalScale, 0.5);
|
||||
expect(updatedVerticalScale, 0.5);
|
||||
expect(didTap, isFalse);
|
||||
|
||||
// Horizontal scaling
|
||||
tester.route(pointer2.move(const Offset(0.0, 20.0)));
|
||||
expect(updatedHorizontalScale, 2.0);
|
||||
expect(updatedVerticalScale, 1.0);
|
||||
|
||||
// Vertical scaling
|
||||
tester.route(pointer2.move(const Offset(10.0, 10.0)));
|
||||
expect(updatedHorizontalScale, 1.0);
|
||||
expect(updatedVerticalScale, 2.0);
|
||||
tester.route(pointer2.move(const Offset(15.0, 25.0)));
|
||||
updatedFocalPoint = null;
|
||||
updatedScale = null;
|
||||
|
||||
// Three-finger scaling
|
||||
final TestPointer pointer3 = TestPointer(3);
|
||||
final PointerDownEvent down3 = pointer3.down(const Offset(25.0, 35.0));
|
||||
|
||||
Reference in New Issue
Block a user