フラッタ:カスタムペイントでドラッグ&ドロップ図形
21204 ワード
イントロ
この記事では、Flutter CustomPaintウィジェットを使用してユーザーインタラクティブドラッグ&ドロップを実装する方法を共有したいと思います.がある
no packages need to be installed
私たちは、フラッタとダートが我々を提供するものだけを使うつもりです.では、ダイビングをしましょう!1 .形状オブジェクトデータを使用した状態ウィジェット
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isDown = false;
double x = 0.0;
double y = 0.0;
int? targetId;
Map<int, Map<String, double>> pathList = {
1: {"x": 100, "y": 100, "r": 50, "color": 0},
2: {"x": 200, "y": 200, "r": 50, "color": 1},
3: {"x": 300, "y": 300, "r": 50, "color": 2},
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(child: Text('dummy text'))
);
}
}
まず、我々は必要StatefulWidget
ユーザーの相互作用に反応する.2 .ウィジェット
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: GestureDetector(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.grey,
child: CustomPaint(
foregroundPainter:
ShapePainter(down: isDown, x: x, y: y, pathList: pathList),
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
)),
) // This trailing comma makes auto-formatting nicer for build methods.
);
}
さて、ウィジェットツリーを埋める必要があります.3 .ユーザインタラクションのキャプチャ
// util function
bool isInObject(Map<String, double> data, double dx, double dy) {
Path _tempPath = Path()
..addOval(Rect.fromCircle(
center: Offset(data['x']!, data['y']!), radius: data['r']!));
return _tempPath.contains(Offset(dx, dy));
}
// event handler
void _down(DragStartDetails details) {
setState(() {
isDown = true;
x = details.localPosition.dx;
y = details.localPosition.dy;
});
}
void _up() {
setState(() {
isDown = false;
targetId = null;
});
}
void _move(DragUpdateDetails details) {
if (isDown) {
setState(() {
x += details.delta.dx;
y += details.delta.dy;
targetId ??= pathList.keys
.firstWhereOrNull((_id) => isInObject(pathList[_id]!, x, y));
if (targetId != null) {
pathList = {
...pathList,
targetId!: {...pathList[targetId!]!, 'x': x, 'y': y}
};
}
});
}
}
// map event handler to pan event
...
body: GestureDetector(
onPanStart: (details) {
_down(details);
},
onPanEnd: (details) {
_up();
},
onPanUpdate: (details) {
_move(details);
},
...
次にイベントハンドラを登録します.インGestureDetector
パンイベントはドラッグ&ドロップです.カスタムペイント&カスタムペイント
class ShapePainter extends CustomPainter {
final colors = [Colors.red, Colors.yellow, Colors.lightBlue];
Path path = Path();
Paint _paint = Paint()
..color = Colors.red
..strokeWidth = 5
..strokeCap = StrokeCap.round;
final bool down;
final double x;
final double y;
Map<int, Map<String, double>> pathList;
ShapePainter({
required this.down,
required this.x,
required this.y,
required this.pathList,
});
@override
void paint(Canvas canvas, Size size) {
for (var pathData in pathList.values) {
_paint = _paint..color = colors[pathData['color']! as int];
path = Path()
..addOval(Rect.fromCircle(
center: Offset(pathData['x']!, pathData['y']!),
radius: pathData['r']!));
canvas.drawPath(path, _paint);
}
}
@override
bool shouldRepaint(ShapePainter oldDelegate) => down;
}
ShapePainterはペイントメソッドを所有している人です.多くの論理がありません、ちょうど上のウィジェットがそれを与えたデータを描いてください.注意shouldRepaint
ユーザーのタッチやマウスがダウンしているときには常に更新されます.結論
私は一般的にキャンバスに興味があります.私はこれがFlutterのカスタム画家を使用してドラッグ&ドロップを実装したい方を助けることができることを願っています.
乾杯!
Reference
この問題について(フラッタ:カスタムペイントでドラッグ&ドロップ図形), 我々は、より多くの情報をここで見つけました https://dev.to/swimmingkiim/flutter-drag-drop-shapes-in-custompaint-3ngjテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol