问题
I have implemented the Scale gesture for the container. Also, I have added onHorizontalDragUpdate and onVerticalDragUpdate. But when I try to add both, I get an exception saying can't implement both with Scale gesture. Even for Pan gesture, it throws the same exception. Below is my code:
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' hide Colors;
import 'dart: math' as math;
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomeState();
}
}
class HomeState extends State<HomeScreen> {
double _scale = 1.0;
double _previousScale;
var yOffset = 400.0;
var xOffset = 50.0;
var rotation = 0.0;
var lastRotation = 0.0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Stack(
children: <Widget>[
stackContainer(),
],
),
);
}
Widget stackContainer() {
return Stack(
children: <Widget>[
Positioned.fromRect(
rect: Rect.fromPoints( Offset(xOffset, yOffset),
Offset(xOffset+250.0, yOffset+100.0)),
child: GestureDetector(
onScaleStart: (scaleDetails) {
_previousScale = _scale;
print(' scaleStarts = ${scaleDetails.focalPoint}');
},
onScaleUpdate: (scaleUpdates){
//ScaleUpdateDetails
rotation += lastRotation - scaleUpdates.rotation;
lastRotation = scaleUpdates.rotation;
print("lastRotation = $lastRotation");
print(' scaleUpdates = ${scaleUpdates.scale} rotation = ${scaleUpdates.rotation}');
setState(() => _scale = _previousScale * scaleUpdates.scale);
},
onScaleEnd: (scaleEndDetails) {
_previousScale = null;
print(' scaleEnds = ${scaleEndDetails.velocity}');
},
child:
Transform(
transform: Matrix4.diagonal3( Vector3(_scale, _scale, _scale))..rotateZ(rotation * math.pi/180.0),
alignment: FractionalOffset.center,
child: Container(
color: Colors.red,
),
)
,
),
),
],
);
}
}
I wanted to move around the red subview and rotate along with the scale.
回答1:
We can use the focalPoint field of ScaleUpdateDetails object, which we get as an argument in the onScaleUpdate function.
Solution related to the above example: We need to update the onScaleUpdate method.
onScaleUpdate: (scaleUpdates) {
lastRotation += scaleUpdates.rotation;
var offset = scaleUpdates.focalPoint;
xOffset = offset.dx;
yOffset = offset.dy;
setState(() => _scale = _previousScale * scaleUpdates.scale);
}
Change 'rect' field of Positioned Widget in above code.
rect: Rect.fromPoints(Offset(xOffset - 125.0, yOffset - 50.0),
Offset(xOffset + 250.0, yOffset + 100.0))
回答2:
Default GestureRecognizer
does not support the recognition of pan/drag and scaling at the same time. I think this is the bug and it should be fixed. To implement such behavior - you need to build you own recogizer RawGestureDetector
based on ImmediateMultiDragGestureRecognizer
gestures.
I have already implemented class PanAndScalingGestureRecognizer
here: https://gist.github.com/comm1x/8ffffd08417053043e079878b4bd8d03
So you can see full example or just copypaste and use.
来源:https://stackoverflow.com/questions/54536275/flutter-how-to-implement-rotate-and-pan-move-gesture-for-any-container