两个工具类
import 'package:flutter/material.dart';
class GestureAngleView extends StatelessWidget{
final double angel;
final Function(double angel, bool end) onChanged;
final List<Widget> Function(BuildContext context, Size size, double radian)buildChildren;
const GestureAngleView(this.angel, this.onChanged, this.buildChildren);
@override
Widget build(BuildContext context) {
return GestureView(
builder: (context, size) {
return Stack(
alignment:Alignment.center ,
children: buildChildren(context, size, angel / 180 * pi),
);
},
onChanged: (point, size, isEnd) {
turn(point, size, isEnd);
},
);
}
void turn(Offset point, Size size, bool isEnd){
var radian = getRadians(size.center(Offset.zero), point);
var angel = getAngel(radian);
onChanged(angel, isEnd);
}
double getRadius(Offset point, Offset center) {
return sqrt(pow((point.dx - center.dx), 2) + pow(point.dy - center.dy, 2));
}
double getRadians(Offset center, Offset point) {
var a = point.dx - center.dx;
var b = center.dy - point.dy;
double radians = atan2(b, a);
return radians < 0 ? -radians : 2 * pi - radians;
}
double getAngel(double radian) {
if(radian >= 2 * pi) {
radian -= 2 * pi;
}
if(radian < 0) {
radian += 2 * pi;
}
return (radian / pi) * 180;
}
}
class GestureView extends StatefulWidget {
final Function(Offset point, Size size, bool end) onChanged;
final Widget Function(BuildContext context, Size size) builder;
const GestureView({@required this.builder, @required this.onChanged, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _GestureState();
}
class _GestureState extends State<GestureView> {
Offset point;
Size size;
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (BuildContext ctx, BoxConstraints constraints) {
double width = constraints.maxWidth;
double height = constraints.maxHeight;
size = Size(width, height);
return Center(child: GestureDetector(
onHorizontalDragDown: (DragDownDetails details) => turn(details.globalPosition, details.localPosition),
onHorizontalDragUpdate: (DragUpdateDetails details) => turn(details.globalPosition, details.localPosition),
onHorizontalDragEnd: (DragEndDetails details) => widget.onChanged(point, size, true),
onVerticalDragDown: (DragDownDetails details) => turn(details.globalPosition, details.localPosition),
onVerticalDragUpdate: (DragUpdateDetails details) => turn(details.globalPosition, details.localPosition),
onVerticalDragEnd: (DragEndDetails details) => widget.onChanged(point, size, true),
child: SizedBox(
width: width,
height: height,
child: widget.builder(context, size),
),
),);
},);
}
void turn(Offset globalPosition, Offset localPosition){
point = localPosition;
widget.onChanged(point, size, false);
}
}