Flutter 拖拽 Draggable DragTarget

在 Flutter 中,实现拖拽功能主要依赖于 Draggable 和 DragTarget 这两个核心组件。Draggable 用于定义可被拖动的"拖拽源",而 DragTarget 用于定义可以接收拖拽元素的"拖拽目标"。

1. Draggable(拖拽源)

Draggable 允许用户通过手势移动组件,并在拖动过程中携带数据。它有几个核心属性:

  • child:正常状态下显示的组件。
  • feedback:拖拽过程中跟随手指移动的组件(通常设置为半透明或带有阴影的副本)。
  • childWhenDragging:拖拽开始后,原位置留下的占位组件(通常设置为灰色或半透明)。也可以不写,这里一般会做半透明效果。
  • data :拖拽时携带的数据,可以是任意类型,传递给 DragTarget。
  • axis :限制拖拽方向,可设置为水平(Axis.horizontal)或垂直(Axis.vertical)。不写表示任意方向。

2. DragTarget(拖拽目标)

DragTarget 是接收拖拽元素的区域。当 Draggable 被拖入该区域时,会触发相应的回调。核心属性包括:收到的数据是一个DragTargetDetails对象。里面有offset,data(就是传递过来的参数)

  • builder:构建目标区域的 UI,可以根据当前是否有拖拽元素进入来改变外观6。
  • onWillAcceptWithDetails 废弃的方法是onWillAccept:判断是否接受当前拖拽的数据,返回 true 表示接受。
  • onAcceptWithDetails 废弃的方法onAccept当用户松手且 onWillAcceptWithDetails 返回 true 时触发,处理接收到的数据
scala 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: HomePage()));
}

class HomePage extends StatefulWidget {
  HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Offset offset = Offset.zero;
  var param = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.blue,
        child: Stack(
          children: [
            Positioned(
              left: 100,
              top: 100,
              child: Draggable(
                // 传递给DragTarget的数据
                data: '123',
                // 拖拽过程中显示的组件
                feedback: Container(width: 100, height: 100, color: Colors.red),

                // 正常状态下显示的组件
                childWhenDragging: Container(
                  width: 200,
                  height: 200,
                  color: Colors.red.withValues(alpha: 0.5),
                ),
                onDragUpdate: (DragUpdateDetails details) {
                  setState(() {
                    offset = details.delta;
                  });
                },
                child: Container(width: 200, height: 200, color: Colors.green),
              ),
            ),
            Positioned(
              right: 20,
              bottom: 200,
              width: 200,
              height: 200,
              child: DragTarget(
                builder: (context, candidateData, rejectedData) {
                  return Container(
                    width: 200,
                    height: 200,
                    color: Colors.yellow,
                    child: Text(param),
                  );
                },
                onAcceptWithDetails: (DragTargetDetails data) {
                  setState(() {
                    param = data.data;
                  });
                },
                onWillAcceptWithDetails: (data) {
                  return true;
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  SecondPage({Key? key}) : super(key: key);

  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(body: Container(child: null, color: Colors.red));
  }
}
相关推荐
恋猫de小郭10 小时前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白10 小时前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫1 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘1 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185821 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙
恋猫de小郭1 天前
Flutter + EmbeddingGemma 2,谷歌发布完全端侧的 AI Edge Foresight
android·前端·flutter
君赏2 天前
基于 FlutterPatch 快速接入 Flutter 热更新
flutter
律宏阔2 天前
Dart FFI 内存管理:用 using + Arena 替代嵌套 try-finally
前端·flutter
律宏阔2 天前
Flutter 调用 Go:从 c-shared + ffigen 到 @Native + Native Assets 踩坑记录
前端·flutter
律宏阔2 天前
Dart FFI 回调无法使用局部变量?使用 NativeCallable.isolateLocal
前端·flutter