Flutter拖拽组件问题:多Draggable移位+DragTarget onAccept无效
问题解决方案
问题1:拖拽物品时其他物品位置偏移
原因
每个Draggable的childWhenDragging设为空Container(),拖拽时原位置失去占位,Row内的其他组件会自动填充空位,导致移位。
解决方法
给childWhenDragging设置和原child相同尺寸的占位容器,保持位置不变:
childWhenDragging: const SizedBox( height: 90.0, width: 90.0, ),
问题2:拖拽到DragTarget后文本框无法显示
原因
DragDropItems是StatelessWidget,无法通过状态更新UI;onAccept是回调方法,不能直接返回Widget来渲染,需要通过状态管理触发UI重建。
解决方法
- 将
DragDropItems改为StatefulWidget,维护拖拽数据状态; - 在
onAccept中更新状态,将拖拽的数据存入列表; - 在UI中根据状态渲染文本框(或展示拖拽的内容)。
修改后的完整代码
import 'package:flutter/material.dart'; class DragDropItems extends StatefulWidget { const DragDropItems({super.key}); @override State<DragDropItems> createState() => _DragDropItemsState(); } class _DragDropItemsState extends State<DragDropItems> { final List<String> _droppedItems = []; final Color color = Colors.black; @override Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( image: DecorationImage( fit: BoxFit.fill, image: AssetImage('assets/images/Environment.png'))), child: Scaffold( backgroundColor: Colors.transparent, body: Stack(children: <Widget>[ Align( alignment: Alignment.center, child: Padding( padding: const EdgeInsets.only(top: 200), child: Column( children: [ DragTarget<String>( onAccept: (data) { setState(() { _droppedItems.add(data); }); }, builder: (_, __, ___) { return Container( width: 300, height: 300, alignment: Alignment.center, child: Image.asset('assets/images/Doggo3.png'), ); }, ), // 根据拖拽的内容渲染文本框或列表 if (_droppedItems.isNotEmpty) Padding( padding: const EdgeInsets.all(15), child: Column( children: _droppedItems.map((item) { return Padding( padding: const EdgeInsets.all(15), child: TextField( decoration: InputDecoration( border: const OutlineInputBorder(), labelText: '拖拽的物品:$item', hintText: '输入相关内容', ), ), ); }).toList(), ), ) ], ))), Align( alignment: Alignment.bottomCenter, child: Padding( padding: const EdgeInsets.only(bottom: 50), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Draggable<String>( data: 'red', feedback: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/cupcake1.png'), )), childWhenDragging: const SizedBox( height: 90.0, width: 90.0, ), child: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/cupcake1.png'), ), ), ), Draggable<String>( data: 'blue', feedback: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/banana1.png'), )), childWhenDragging: const SizedBox( height: 90.0, width: 90.0, ), child: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/banana1.png'), ), ), ), Draggable<String>( data: 'green', feedback: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/hamburger1.png'), )), childWhenDragging: const SizedBox( height: 90.0, width: 90.0, ), child: const SizedBox( height: 90.0, width: 90.0, child: Center( child: Image.asset('assets/images/hamburger1.png'), ), ), ), ], ))) ]), )); } }
代码说明
- 改为
StatefulWidget后,通过setState更新_droppedItems列表,触发UI重建; DragTarget下方添加了条件渲染,当有物品拖拽进来时显示对应文本框;- 每个
Draggable的childWhenDragging设置了固定尺寸的占位,避免其他组件移位。
内容的提问来源于stack exchange,提问作者awwd
相关产品推荐
相关产品推荐

