如何使用 onPanUpdate 调用缩放 GestureDetector?
How to zoom a GestureDetector with onPanUpdate call?
我正在开发一个绘图应用程序。我想在 canvas 上启用绘图和缩放绘图。到目前为止,我尝试通过在 InteractiveViewer 中包装 GestureDetector 并使用 AbsorbPointer 打开和关闭缩放模式来实现它。请参阅下面的最小演示代码。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new IssueExamplePage(),
debugShowCheckedModeBanner: false,
));
class IssueExamplePage extends StatefulWidget {
@override
_IssueExamplePageState createState() => _IssueExamplePageState();
}
class _IssueExamplePageState extends State<IssueExamplePage> {
bool drawingBlocked = false;
List<Offset> points = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.grey,
padding: EdgeInsets.all(5),
child: Container(
color: Colors.white,
child: InteractiveViewer(
child: AbsorbPointer(
absorbing: drawingBlocked,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onPanUpdate: (details) {
RenderBox renderBox = context.findRenderObject();
Offset cursorLocation = renderBox.globalToLocal(details.localPosition);
setState(() {
points = List.of(points)..add(cursorLocation);
});
},
onPanEnd: (details) {
setState(() {
points = List.of(points)..add(null);
});
},
child: CustomPaint(
painter: MyPainter(points),
size: Size.infinite
),
),
),
),
),
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
child: Icon(drawingBlocked? CupertinoIcons.hand_raised_fill : CupertinoIcons.hand_raised),
onPressed: () {
setState(() {
drawingBlocked = !drawingBlocked;
});
}
),
SizedBox(
height: 10
),
FloatingActionButton(
child: Icon(Icons.clear),
onPressed: () {
setState(() {
points = [];
});
}
),
SizedBox(
height: 20
),
],
),
);
}
}
class MyPainter extends CustomPainter {
MyPainter(this.points);
List<Offset> points;
Paint paintBrush = Paint()
..color = Colors.blue
..strokeWidth = 5
..strokeJoin = StrokeJoin.round
..strokeCap = StrokeCap.round;
@override
void paint(Canvas canvas, Size size) {
for (int i = 0; i < points.length - 1; i++) {
if (points[i] != null && points[i + 1] != null) {
canvas.drawLine(points[i], points[i + 1], paintBrush);
}
}
}
@override
bool shouldRepaint(MyPainter oldDelegate) {
return points != oldDelegate.points;
}
}
但是,有了这个实现,OnPanUpdate 会延迟工作(请参阅 Flutter onPanStart invokes late when the widget is wrapped inside InteractiveViewer)。是否有任何其他方法可以达到预期的结果(缩放和绘图),或者是否可以修复 OnPanUpdate 延迟?
更新:我找到了某种解决方案。您可以使用 Listener 而不是 GestureDetector(它可以替代大部分参数:onPanStart -> onPointerDown、onPanUpdate -> onPointerMove 等)。但是 GestureDetector 似乎没有修复。
我正在开发一个绘图应用程序。我想在 canvas 上启用绘图和缩放绘图。到目前为止,我尝试通过在 InteractiveViewer 中包装 GestureDetector 并使用 AbsorbPointer 打开和关闭缩放模式来实现它。请参阅下面的最小演示代码。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new IssueExamplePage(),
debugShowCheckedModeBanner: false,
));
class IssueExamplePage extends StatefulWidget {
@override
_IssueExamplePageState createState() => _IssueExamplePageState();
}
class _IssueExamplePageState extends State<IssueExamplePage> {
bool drawingBlocked = false;
List<Offset> points = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.grey,
padding: EdgeInsets.all(5),
child: Container(
color: Colors.white,
child: InteractiveViewer(
child: AbsorbPointer(
absorbing: drawingBlocked,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onPanUpdate: (details) {
RenderBox renderBox = context.findRenderObject();
Offset cursorLocation = renderBox.globalToLocal(details.localPosition);
setState(() {
points = List.of(points)..add(cursorLocation);
});
},
onPanEnd: (details) {
setState(() {
points = List.of(points)..add(null);
});
},
child: CustomPaint(
painter: MyPainter(points),
size: Size.infinite
),
),
),
),
),
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
child: Icon(drawingBlocked? CupertinoIcons.hand_raised_fill : CupertinoIcons.hand_raised),
onPressed: () {
setState(() {
drawingBlocked = !drawingBlocked;
});
}
),
SizedBox(
height: 10
),
FloatingActionButton(
child: Icon(Icons.clear),
onPressed: () {
setState(() {
points = [];
});
}
),
SizedBox(
height: 20
),
],
),
);
}
}
class MyPainter extends CustomPainter {
MyPainter(this.points);
List<Offset> points;
Paint paintBrush = Paint()
..color = Colors.blue
..strokeWidth = 5
..strokeJoin = StrokeJoin.round
..strokeCap = StrokeCap.round;
@override
void paint(Canvas canvas, Size size) {
for (int i = 0; i < points.length - 1; i++) {
if (points[i] != null && points[i + 1] != null) {
canvas.drawLine(points[i], points[i + 1], paintBrush);
}
}
}
@override
bool shouldRepaint(MyPainter oldDelegate) {
return points != oldDelegate.points;
}
}
但是,有了这个实现,OnPanUpdate 会延迟工作(请参阅 Flutter onPanStart invokes late when the widget is wrapped inside InteractiveViewer)。是否有任何其他方法可以达到预期的结果(缩放和绘图),或者是否可以修复 OnPanUpdate 延迟?
更新:我找到了某种解决方案。您可以使用 Listener 而不是 GestureDetector(它可以替代大部分参数:onPanStart -> onPointerDown、onPanUpdate -> onPointerMove 等)。但是 GestureDetector 似乎没有修复。