并排DragTarget组件onLeave事件失效问题求助
解决方案
方案1:利用DragTarget内置状态(最简洁)
直接通过builder参数里的accepted列表判断当前是否有拖拽项在目标区域内,动态设置颜色,不需要手动维护额外状态:
return DragTarget<int>( builder: ( BuildContext context, List<int?> accepted, List<Object?> rejected, ) { // 有被接受的拖拽项时显示红色,否则显示蓝色 final currentColor = accepted.isNotEmpty ? Colors.red : Colors.blue; return Container( height: size.height, width: size.width, color: currentColor, ); }, onWillAcceptWithDetails: (DragTargetDetails<int> details) { return true; }, onAcceptWithDetails: (DragTargetDetails<int> details) { print('dropped'); }, );
原理:DragTarget内部会自动跟踪拖拽项的进入/离开状态,accepted列表会在拖拽项进入时填充、离开时清空,触发builder重建。这种方式完全避免了手动setState带来的状态冲突问题。
方案2:给每个DragTarget分配独立状态变量
如果需要更灵活的状态控制(比如保存拖拽前的初始颜色),可以给每个DragTarget维护独立的状态:
- 在父组件中用Map存储每个目标的颜色(给每个DragTarget分配唯一ID):
Map<int, Color> _targetColors = { 0: Colors.transparent, 1: Colors.transparent, };
- 每个DragTarget绑定对应的ID,更新状态时只修改自己的颜色:
// 第一个DragTarget,ID为0 DragTarget<int>( builder: (context, accepted, rejected) { return Container( height: size.height, width: size.width, color: _targetColors[0], ); }, onWillAcceptWithDetails: (details) { setState(() { _targetColors[0] = Colors.red; }); return true; }, onLeave: (data) { setState(() { _targetColors[0] = Colors.blue; }); }, onAcceptWithDetails: (details) { setState(() { _targetColors[0] = Colors.blue; print('dropped on target 0'); }); }, ), // 第二个DragTarget,ID为1 DragTarget<int>( builder: (context, accepted, rejected) { return Container( height: size.height, width: size.width, color: _targetColors[1], ); }, onWillAcceptWithDetails: (details) { setState(() { _targetColors[1] = Colors.red; }); return true; }, onLeave: (data) { setState(() { _targetColors[1] = Colors.blue; }); }, onAcceptWithDetails: (details) { setState(() { _targetColors[1] = Colors.blue; print('dropped on target 1'); }); }, ),
原理:每个DragTarget的状态独立存储,切换拖拽时两个setState修改的是不同的变量,不会互相覆盖。
问题根源
你遇到的本质问题是:两个DragTarget共享了同一个状态变量normalArea,或者在同一帧内连续触发的setState会覆盖之前的状态更新。当从A拖拽到B时,A的onLeave先把颜色设为蓝色,紧接着B的onWillAcceptWithDetails把颜色设为红色,最终状态被后面的操作覆盖,导致A的颜色没有正确更新。
内容的提问来源于stack exchange,提问作者Alexandre B.
相关产品推荐
相关产品推荐

