Flutter中Draggable组件无法拖拽问题求助
Flutter Draggable组件无响应问题解决
问题现象
- 实现的两个雷达组件无法拖拽,无任何交互反馈,控制台无输出或报错
- Android、Windows平台测试均无法触发手势事件,尝试
HitTestBehavior.opaque和Positioned组件未解决
问题根源
- CustomPaint无有效占位:
CustomPaint未设置size,组件实际尺寸为0×0,手势检测无法命中目标区域 - 组件定位不匹配:Stack中的
RadarWidget未定位,默认堆叠在左上角,与绘制的图形位置脱节 - 拖拽状态未同步:未在拖拽结束时更新
RadarPoint的位置,导致拖拽后组件位置不变
修复方案
- 给
CustomPaint指定明确尺寸,确保组件有可交互的区域 - 使用
Positioned在Stack中定位每个RadarWidget,使其与绘制图形的中心对齐 - 在
onDragEnd回调中更新RadarPoint的position,同步拖拽后的位置
修改后的完整代码
import 'dart:math' as math; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; class RadarPoint { Offset position; int stateValue; double orientation; RadarPoint({ required this.position, required this.stateValue, required this.orientation, }); } final List<RadarPoint> points = [ RadarPoint(position: const Offset(300, 60), orientation: 0, stateValue: 0), RadarPoint(position: const Offset(300, 220), orientation: 45, stateValue: 1), ]; const double maxAngle = 150; const double diameter = 200; const List<Color> distanceColors = [ Colors.red, Colors.orange, Colors.yellow, Colors.green, ]; class RadarPainter extends CustomPainter { RadarPoint point; double diameter; List<Color> distanceColors; double maxAngle; RadarPainter({ required this.point, required this.diameter, required this.distanceColors, required this.maxAngle, }); double degreesToRads(double deg) => deg * math.pi / 180.0; double currentDiameter(int i) => diameter / distanceColors.length * (i + 1); @override void paint(Canvas canvas, Size size) { // 将绘制原点移到组件中心,避免偏移 canvas.translate(size.width / 2, size.height / 2); for (var i = distanceColors.length - 1; i > -1; i--) { if (i >= point.stateValue) { canvas.drawArc( Rect.fromCenter( center: Offset.zero, height: currentDiameter(i), width: currentDiameter(i), ), degreesToRads(point.orientation), degreesToRads(maxAngle), true, Paint()..color = distanceColors[i].withOpacity(0.5), ); } } canvas.drawCircle(Offset.zero, 5, Paint()..color = Colors.black); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; } class RadarWidget extends StatefulWidget { final RadarPoint point; const RadarWidget({super.key, required this.point}); @override State<RadarWidget> createState() => _RadarWidgetState(); } class _RadarWidgetState extends State<RadarWidget> { late RadarPoint point; @override void initState() { super.initState(); point = widget.point; } Widget _feedback() { return SizedBox( width: diameter, height: diameter, child: CustomPaint( painter: RadarPainter( point: point, diameter: diameter * 1.2, distanceColors: distanceColors, maxAngle: maxAngle, ), ), ); } @override Widget build(BuildContext context) { return Positioned( left: point.position.dx - diameter / 2, top: point.position.dy - diameter / 2, child: Draggable<RadarPoint>( data: point, feedback: _feedback(), onDragStarted: () { print('onDragStarted'); }, onDragUpdate: (details) { print('onDragUpdate'); }, onDragEnd: (details) { print('onDragEnd'); setState(() { // 更新位置,基于拖拽结束时的全局坐标 point.position = details.offset - Offset(diameter/2, diameter/2); }); }, onDraggableCanceled: (velocity, offset) { print('onDraggableCanceled'); }, hitTestBehavior: HitTestBehavior.opaque, child: SizedBox( width: diameter, height: diameter, child: CustomPaint( painter: RadarPainter( point: point, diameter: diameter, distanceColors: distanceColors, maxAngle: maxAngle, ), ), ), ), ); } } class App extends StatelessWidget { App({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Stack( children: [ RadarWidget(point: points[0]), RadarWidget(point: points[1]), ], ), ), ); } } Future<void> main() async { debugPrintGestureArenaDiagnostics = false; runApp(App()); }
内容的提问来源于stack exchange,提问作者Mauricio
相关产品推荐
相关产品推荐

