You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter拖拽组件问题:多Draggable移位+DragTarget onAccept无效

问题解决方案

问题1:拖拽物品时其他物品位置偏移

原因

每个Draggable的childWhenDragging设为空Container(),拖拽时原位置失去占位,Row内的其他组件会自动填充空位,导致移位。

解决方法

给childWhenDragging设置和原child相同尺寸的占位容器,保持位置不变:

childWhenDragging: const SizedBox(
  height: 90.0,
  width: 90.0,
),

问题2:拖拽到DragTarget后文本框无法显示

原因

  1. DragDropItems是StatelessWidget,无法通过状态更新UI;
  2. onAccept是回调方法,不能直接返回Widget来渲染,需要通过状态管理触发UI重建。

解决方法

  1. 将DragDropItems改为StatefulWidget,维护拖拽数据状态;
  2. 在onAccept中更新状态,将拖拽的数据存入列表;
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 14:12:26