Flutter拖拽组件Draggable(1)

描述:

使用Draggable(LongPressDraggable长按拖拽组件属性类似Draggable) 和 DragTarget结合,实现组件的拖拽效果

效果图:

代码:


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

  @override
  State<DraggblePage> createState() => _DraggblePageState();
}

class _DraggblePageState extends State<DraggblePage> {
  bool _accept = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Draggable"),
      ),
      body: Center(
        child: Column(
          children: [
            Draggable(
              //用于限制child可移动的方向,默认null允许任何方向
              // axis: null,
              //拖动对象携带的数据可传值给目标控件
              data: true,
              child: _accept
                  ? Container(height: 100, width: 100)
                  : _buildDraggable(context),
              //拖动时的部件
              feedback: _buildFeedback(context),
              //拖动时,child部件的显示样式
              childWhenDragging: Container(height: 100, width: 100),

              //feedback左上角,相对点击锚点的偏移量
              // dragAnchorStrategy: (draggable, context, position) {
              // },

              //拖动时的锚点的x,y与目标范围的相差偏移量,
              //锚点拖动到灰色区域才可触发 DragTarget的onAccept事件
              feedbackOffset: const Offset(0, 0),

              //开始拖动时回调
              onDragStarted: () {
                print("----------onDragStarted");
              },
              //拖动中的回调
              onDragUpdate: (details) {
                print("----------onDragUpdate");
              },
              //拖动到DragTarget控件上时松手后被目标[DragTarget]接受时的回调。
              onDragCompleted: () {
                print("----------onDragCompleted");
              },

              //检测未拖动到目标[DragTarget]控件上时回调。
              onDraggableCanceled: (velocity, offset) {
                print("----------onDraggableCanceled");
              },
              //拖动结束时回调
              onDragEnd: (details) {
                print("----------onDragEnd");
              },
            ),
            const SizedBox(height: 200),
            //目标控件
            DragTarget<bool>(
              builder: (BuildContext context, List<dynamic> candidateData,
                  List<dynamic> rejectedData) {
                return _accept
                    ? _buildDraggable(context)
                    : _buildDragTarget(context);
              },
              //当 [Draggable] 移动到 [DragTarget] 内时的回调。 返回true松开会触发onAccept onAcceptWithDetails,返回false则不会触发onAccept onAcceptWithDetails
              onWillAccept: (bool? value) {
                print("----------onWillAccept");
                return true;
              },
              //目标控件接收成功的回调
              onAccept: (bool value) {
                setState(() {
                  _accept = value;
                });
                print("----------onAccept");
              },

              ///用于确定 [DragTarget] 接受信息的签名 包括锚点的位置等。
              onAcceptWithDetails: (details) {
                print("----------onAcceptWithDetails");
              },
              // 当 [Draggable] 在 [DragTarget] 内离开时的回调。
              onLeave: (bool? value) {
                print("----------onLeave");
              },
              //当 [Draggable] 在 [DragTarget] 内移动时的回调。
              onMove: (details) {
                print("----------onMove");
              },
            )
          ],
        ),
      ),
    );
  }

  Widget _buildDraggable(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.teal,
        borderRadius: BorderRadius.circular(4),
      ),
      child: const Text(
        'Draggable',
        style: TextStyle(color: Colors.white, fontSize: 18),
      ),
    );
  }

  Widget _buildFeedback(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.teal,
        borderRadius: BorderRadius.circular(4),
      ),
      child: const Text(
        'Feedback',
        style: TextStyle(color: Colors.white, fontSize: 18),
      ),
    );
  }

  Widget _buildDragTarget(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(4),
        color: Colors.grey,
      ),
      child: Text("DragTarget"),
    );
  }
}

注意:

details.offset.dy的值包含状态栏和appbar的高度

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜鸡的日志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值