mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
panningDirection parameter added to InteractiveViewer (#109014)
This commit is contained in:
parent
8074811c2f
commit
0ad0a56e86
@ -34,7 +34,7 @@ class MyStatelessWidget extends StatelessWidget {
|
|||||||
const int columnCount = 6;
|
const int columnCount = 6;
|
||||||
|
|
||||||
return InteractiveViewer(
|
return InteractiveViewer(
|
||||||
alignPanAxis: true,
|
panAxis: PanAxis.aligned,
|
||||||
constrained: false,
|
constrained: false,
|
||||||
scaleEnabled: false,
|
scaleEnabled: false,
|
||||||
child: Table(
|
child: Table(
|
||||||
|
@ -67,7 +67,12 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
InteractiveViewer({
|
InteractiveViewer({
|
||||||
super.key,
|
super.key,
|
||||||
this.clipBehavior = Clip.hardEdge,
|
this.clipBehavior = Clip.hardEdge,
|
||||||
|
@Deprecated(
|
||||||
|
'Use panAxis instead. '
|
||||||
|
'This feature was deprecated after v3.3.0-0.5.pre.',
|
||||||
|
)
|
||||||
this.alignPanAxis = false,
|
this.alignPanAxis = false,
|
||||||
|
this.panAxis = PanAxis.free,
|
||||||
this.boundaryMargin = EdgeInsets.zero,
|
this.boundaryMargin = EdgeInsets.zero,
|
||||||
this.constrained = true,
|
this.constrained = true,
|
||||||
// These default scale values were eyeballed as reasonable limits for common
|
// These default scale values were eyeballed as reasonable limits for common
|
||||||
@ -83,6 +88,7 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
this.transformationController,
|
this.transformationController,
|
||||||
required Widget this.child,
|
required Widget this.child,
|
||||||
}) : assert(alignPanAxis != null),
|
}) : assert(alignPanAxis != null),
|
||||||
|
assert(panAxis != null),
|
||||||
assert(child != null),
|
assert(child != null),
|
||||||
assert(constrained != null),
|
assert(constrained != null),
|
||||||
assert(minScale != null),
|
assert(minScale != null),
|
||||||
@ -114,7 +120,12 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
InteractiveViewer.builder({
|
InteractiveViewer.builder({
|
||||||
super.key,
|
super.key,
|
||||||
this.clipBehavior = Clip.hardEdge,
|
this.clipBehavior = Clip.hardEdge,
|
||||||
|
@Deprecated(
|
||||||
|
'Use panAxis instead. '
|
||||||
|
'This feature was deprecated after v3.3.0-0.5.pre.',
|
||||||
|
)
|
||||||
this.alignPanAxis = false,
|
this.alignPanAxis = false,
|
||||||
|
this.panAxis = PanAxis.free,
|
||||||
this.boundaryMargin = EdgeInsets.zero,
|
this.boundaryMargin = EdgeInsets.zero,
|
||||||
// These default scale values were eyeballed as reasonable limits for common
|
// These default scale values were eyeballed as reasonable limits for common
|
||||||
// use cases.
|
// use cases.
|
||||||
@ -128,7 +139,7 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
this.scaleFactor = 200.0,
|
this.scaleFactor = 200.0,
|
||||||
this.transformationController,
|
this.transformationController,
|
||||||
required InteractiveViewerWidgetBuilder this.builder,
|
required InteractiveViewerWidgetBuilder this.builder,
|
||||||
}) : assert(alignPanAxis != null),
|
}) : assert(panAxis != null),
|
||||||
assert(builder != null),
|
assert(builder != null),
|
||||||
assert(minScale != null),
|
assert(minScale != null),
|
||||||
assert(minScale > 0),
|
assert(minScale > 0),
|
||||||
@ -158,6 +169,8 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
/// Defaults to [Clip.hardEdge].
|
/// Defaults to [Clip.hardEdge].
|
||||||
final Clip clipBehavior;
|
final Clip clipBehavior;
|
||||||
|
|
||||||
|
/// This property is deprecated, please use [panAxis] instead.
|
||||||
|
///
|
||||||
/// If true, panning is only allowed in the direction of the horizontal axis
|
/// If true, panning is only allowed in the direction of the horizontal axis
|
||||||
/// or the vertical axis.
|
/// or the vertical axis.
|
||||||
///
|
///
|
||||||
@ -169,8 +182,25 @@ class InteractiveViewer extends StatefulWidget {
|
|||||||
/// See also:
|
/// See also:
|
||||||
/// * [constrained], which has an example of creating a table that uses
|
/// * [constrained], which has an example of creating a table that uses
|
||||||
/// alignPanAxis.
|
/// alignPanAxis.
|
||||||
|
@Deprecated(
|
||||||
|
'Use panAxis instead. '
|
||||||
|
'This feature was deprecated after v3.3.0-0.5.pre.',
|
||||||
|
)
|
||||||
final bool alignPanAxis;
|
final bool alignPanAxis;
|
||||||
|
|
||||||
|
/// When set to [PanAxis.aligned], panning is only allowed in the horizontal
|
||||||
|
/// axis or the vertical axis, diagonal panning is not allowed.
|
||||||
|
///
|
||||||
|
/// When set to [PanAxis.vertical] or [PanAxis.horizontal] panning is only
|
||||||
|
/// allowed in the specified axis. For example, if set to [PanAxis.vertical],
|
||||||
|
/// panning will only be allowed in the vertical axis. And if set to [PanAxis.horizontal],
|
||||||
|
/// panning will only be allowed in the horizontal axis.
|
||||||
|
///
|
||||||
|
/// When set to [PanAxis.free] panning is allowed in all directions.
|
||||||
|
///
|
||||||
|
/// Defaults to [PanAxis.free].
|
||||||
|
final PanAxis panAxis;
|
||||||
|
|
||||||
/// A margin for the visible boundaries of the child.
|
/// A margin for the visible boundaries of the child.
|
||||||
///
|
///
|
||||||
/// Any transformation that results in the viewport being able to view outside
|
/// Any transformation that results in the viewport being able to view outside
|
||||||
@ -507,7 +537,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
final GlobalKey _parentKey = GlobalKey();
|
final GlobalKey _parentKey = GlobalKey();
|
||||||
Animation<Offset>? _animation;
|
Animation<Offset>? _animation;
|
||||||
late AnimationController _controller;
|
late AnimationController _controller;
|
||||||
Axis? _panAxis; // Used with alignPanAxis.
|
Axis? _currentAxis; // Used with panAxis.
|
||||||
Offset? _referenceFocalPoint; // Point where the current gesture began.
|
Offset? _referenceFocalPoint; // Point where the current gesture began.
|
||||||
double? _scaleStart; // Scale value at start of scaling gesture.
|
double? _scaleStart; // Scale value at start of scaling gesture.
|
||||||
double? _rotationStart = 0.0; // Rotation at start of rotation gesture.
|
double? _rotationStart = 0.0; // Rotation at start of rotation gesture.
|
||||||
@ -566,9 +596,26 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
return matrix.clone();
|
return matrix.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Offset alignedTranslation = widget.alignPanAxis && _panAxis != null
|
late final Offset alignedTranslation;
|
||||||
? _alignAxis(translation, _panAxis!)
|
|
||||||
: translation;
|
if (_currentAxis != null) {
|
||||||
|
switch(widget.panAxis){
|
||||||
|
case PanAxis.horizontal:
|
||||||
|
alignedTranslation = _alignAxis(translation, Axis.horizontal);
|
||||||
|
break;
|
||||||
|
case PanAxis.vertical:
|
||||||
|
alignedTranslation = _alignAxis(translation, Axis.vertical);
|
||||||
|
break;
|
||||||
|
case PanAxis.aligned:
|
||||||
|
alignedTranslation = _alignAxis(translation, _currentAxis!);
|
||||||
|
break;
|
||||||
|
case PanAxis.free:
|
||||||
|
alignedTranslation = translation;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alignedTranslation = translation;
|
||||||
|
}
|
||||||
|
|
||||||
final Matrix4 nextMatrix = matrix.clone()..translate(
|
final Matrix4 nextMatrix = matrix.clone()..translate(
|
||||||
alignedTranslation.dx,
|
alignedTranslation.dx,
|
||||||
@ -734,7 +781,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
_gestureType = null;
|
_gestureType = null;
|
||||||
_panAxis = null;
|
_currentAxis = null;
|
||||||
_scaleStart = _transformationController!.value.getMaxScaleOnAxis();
|
_scaleStart = _transformationController!.value.getMaxScaleOnAxis();
|
||||||
_referenceFocalPoint = _transformationController!.toScene(
|
_referenceFocalPoint = _transformationController!.toScene(
|
||||||
details.localFocalPoint,
|
details.localFocalPoint,
|
||||||
@ -825,7 +872,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
widget.onInteractionUpdate?.call(details);
|
widget.onInteractionUpdate?.call(details);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_panAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
|
_currentAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
|
||||||
// Translate so that the same point in the scene is underneath the
|
// Translate so that the same point in the scene is underneath the
|
||||||
// focal point before and after the movement.
|
// focal point before and after the movement.
|
||||||
final Offset translationChange = focalPointScene - _referenceFocalPoint!;
|
final Offset translationChange = focalPointScene - _referenceFocalPoint!;
|
||||||
@ -853,13 +900,13 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
_controller.reset();
|
_controller.reset();
|
||||||
|
|
||||||
if (!_gestureIsSupported(_gestureType)) {
|
if (!_gestureIsSupported(_gestureType)) {
|
||||||
_panAxis = null;
|
_currentAxis = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the scale ended with enough velocity, animate inertial movement.
|
// If the scale ended with enough velocity, animate inertial movement.
|
||||||
if (_gestureType != _GestureType.pan || details.velocity.pixelsPerSecond.distance < kMinFlingVelocity) {
|
if (_gestureType != _GestureType.pan || details.velocity.pixelsPerSecond.distance < kMinFlingVelocity) {
|
||||||
_panAxis = null;
|
_currentAxis = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,7 +994,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
|
|||||||
// Handle inertia drag animation.
|
// Handle inertia drag animation.
|
||||||
void _onAnimate() {
|
void _onAnimate() {
|
||||||
if (!_controller.isAnimating) {
|
if (!_controller.isAnimating) {
|
||||||
_panAxis = null;
|
_currentAxis = null;
|
||||||
_animation?.removeListener(_onAnimate);
|
_animation?.removeListener(_onAnimate);
|
||||||
_animation = null;
|
_animation = null;
|
||||||
_controller.reset();
|
_controller.reset();
|
||||||
@ -1296,3 +1343,20 @@ Axis? _getPanAxis(Offset point1, Offset point2) {
|
|||||||
final double y = point2.dy - point1.dy;
|
final double y = point2.dy - point1.dy;
|
||||||
return x.abs() > y.abs() ? Axis.horizontal : Axis.vertical;
|
return x.abs() > y.abs() ? Axis.horizontal : Axis.vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This enum is used to specify the behavior of the [InteractiveViewer] when
|
||||||
|
/// the user drags the viewport.
|
||||||
|
enum PanAxis{
|
||||||
|
/// The user can only pan the viewport along the horizontal axis.
|
||||||
|
horizontal,
|
||||||
|
|
||||||
|
/// The user can only pan the viewport along the vertical axis.
|
||||||
|
vertical,
|
||||||
|
|
||||||
|
/// The user can pan the viewport along the horizontal and vertical axes
|
||||||
|
/// but not diagonally.
|
||||||
|
aligned,
|
||||||
|
|
||||||
|
/// The user can pan the viewport freely in any direction.
|
||||||
|
free,
|
||||||
|
}
|
||||||
|
@ -288,14 +288,52 @@ void main() {
|
|||||||
expect(transformationController.value.getMaxScaleOnAxis(), minScale);
|
expect(transformationController.value.getMaxScaleOnAxis(), minScale);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('alignPanAxis allows panning in one direction only for diagonal gesture', (WidgetTester tester) async {
|
testWidgets('PanAxis.free allows panning in all directions for diagonal gesture', (WidgetTester tester) async {
|
||||||
final TransformationController transformationController = TransformationController();
|
final TransformationController transformationController = TransformationController();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: InteractiveViewer(
|
child: InteractiveViewer(
|
||||||
alignPanAxis: true,
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 20.0,
|
||||||
|
childOffset.dy + 20.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation has only happened along the y axis (the default axis when
|
||||||
|
// a gesture is perfectly at 45 degrees to the axes).
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.x, childOffset.dx - childInterior.dx);
|
||||||
|
expect(translation.y, childOffset.dy - childInterior.dy);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.aligned allows panning in one direction only for diagonal gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.aligned,
|
||||||
boundaryMargin: const EdgeInsets.all(double.infinity),
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
transformationController: transformationController,
|
transformationController: transformationController,
|
||||||
child: const SizedBox(width: 200.0, height: 200.0),
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
@ -327,14 +365,14 @@ void main() {
|
|||||||
expect(translation.y, childOffset.dy - childInterior.dy);
|
expect(translation.y, childOffset.dy - childInterior.dy);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('alignPanAxis allows panning in one direction only for horizontal leaning gesture', (WidgetTester tester) async {
|
testWidgets('PanAxis.aligned allows panning in one direction only for horizontal leaning gesture', (WidgetTester tester) async {
|
||||||
final TransformationController transformationController = TransformationController();
|
final TransformationController transformationController = TransformationController();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: InteractiveViewer(
|
child: InteractiveViewer(
|
||||||
alignPanAxis: true,
|
panAxis: PanAxis.aligned,
|
||||||
boundaryMargin: const EdgeInsets.all(double.infinity),
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
transformationController: transformationController,
|
transformationController: transformationController,
|
||||||
child: const SizedBox(width: 200.0, height: 200.0),
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
@ -366,6 +404,240 @@ void main() {
|
|||||||
expect(translation.y, 0.0);
|
expect(translation.y, 0.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.horizontal allows panning in the horizontal direction only for diagonal gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.horizontal,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 20.0,
|
||||||
|
childOffset.dy + 20.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation has only happened along the x axis (the default axis when
|
||||||
|
// a gesture is perfectly at 45 degrees to the axes).
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.x, childOffset.dx - childInterior.dx);
|
||||||
|
expect(translation.y, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.horizontal allows panning in the horizontal direction only for horizontal leaning gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.horizontal,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a horizontally leaning diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 20.0,
|
||||||
|
childOffset.dy + 10.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation happened only along the x axis because that's the axis that
|
||||||
|
// had been set to the panningDirection parameter.
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.x, childOffset.dx - childInterior.dx);
|
||||||
|
expect(translation.y, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.horizontal does not allow panning in vertical direction on vertical gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.horizontal,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a horizontally leaning diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 0.0,
|
||||||
|
childOffset.dy + 10.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation didn't happen because the only axis allowed to do panning
|
||||||
|
// is the horizontal.
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.x, 0.0);
|
||||||
|
expect(translation.y, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.vertical allows panning in the vertical direction only for diagonal gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.vertical,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 20.0,
|
||||||
|
childOffset.dy + 20.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation has only happened along the x axis (the default axis when
|
||||||
|
// a gesture is perfectly at 45 degrees to the axes).
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.y, childOffset.dy - childInterior.dy);
|
||||||
|
expect(translation.x, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.vertical allows panning in the vertical direction only for vertical leaning gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.vertical,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a horizontally leaning diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 20.0,
|
||||||
|
childOffset.dy + 10.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation happened only along the x axis because that's the axis that
|
||||||
|
// had been set to the panningDirection parameter.
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.y, childOffset.dy - childInterior.dy);
|
||||||
|
expect(translation.x, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('PanAxis.vertical does not allow panning in horizontal direction on vertical gesture', (WidgetTester tester) async {
|
||||||
|
final TransformationController transformationController = TransformationController();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
panAxis: PanAxis.vertical,
|
||||||
|
boundaryMargin: const EdgeInsets.all(double.infinity),
|
||||||
|
transformationController: transformationController,
|
||||||
|
child: const SizedBox(width: 200.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(transformationController.value, equals(Matrix4.identity()));
|
||||||
|
|
||||||
|
// Perform a horizontally leaning diagonal drag gesture.
|
||||||
|
final Offset childOffset = tester.getTopLeft(find.byType(SizedBox));
|
||||||
|
final Offset childInterior = Offset(
|
||||||
|
childOffset.dx + 10.0,
|
||||||
|
childOffset.dy + 0.0,
|
||||||
|
);
|
||||||
|
final TestGesture gesture = await tester.startGesture(childInterior);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.moveTo(childOffset);
|
||||||
|
await tester.pump();
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Translation didn't happen because the only axis allowed to do panning
|
||||||
|
// is the horizontal.
|
||||||
|
final Vector3 translation = transformationController.value.getTranslation();
|
||||||
|
expect(translation.x, 0.0);
|
||||||
|
expect(translation.y, 0.0);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('inertia fling and boundary sliding', (WidgetTester tester) async {
|
testWidgets('inertia fling and boundary sliding', (WidgetTester tester) async {
|
||||||
final TransformationController transformationController = TransformationController();
|
final TransformationController transformationController = TransformationController();
|
||||||
const double boundaryMargin = 50.0;
|
const double boundaryMargin = 50.0;
|
||||||
@ -519,7 +791,7 @@ void main() {
|
|||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: InteractiveViewer(
|
child: InteractiveViewer(
|
||||||
alignPanAxis: true,
|
panAxis: PanAxis.aligned,
|
||||||
boundaryMargin: const EdgeInsets.all(boundaryMargin),
|
boundaryMargin: const EdgeInsets.all(boundaryMargin),
|
||||||
minScale: minScale,
|
minScale: minScale,
|
||||||
transformationController: transformationController,
|
transformationController: transformationController,
|
||||||
|
Loading…
Reference in New Issue
Block a user