Flutter--拖拽组件(支持多组数据)

通用可拖拽GragGridView 

class SingleDragGridView<T extends Object> extends StatefulWidget {

  final List<T> dataList;
  final Widget Function(BuildContext contex, int index, T data) itemBuilder;
  final SliverGridDelegate gridDelegate;
  final Function(List<T> newList) onChanged;

  final ScrollPhysics? physics;
  final bool? shrinkWrap;
  final Axis? scrollDirection;
  final EdgeInsetsGeometry? padding;

  const SingleDragGridView({
    super.key,
    required this.gridDelegate,
    required this.itemBuilder,
    required this.dataList,
    required this.onChanged,
    this.physics,
    this.shrinkWrap,
    this.scrollDirection,
    this.padding
  });

  @override
  State<StatefulWidget> createState() => _SingleDragGridViewState<T>();
}

class _SingleDragGridViewState<T extends Object> extends State<SingleDragGridView<T>> {

  List<T> dataList = [];
  T? movingData;

  @override
  void initState() {
    super.initState();
    dataList.addAll(widget.dataList);
  }

  @override
  void didUpdateWidget(covariant SingleDragGridView<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (dataList != widget.dataList) dataList = [...widget.dataList];
  }

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      padding: widget.padding,
      gridDelegate: widget.gridDelegate,
      physics: widget.physics,
      shrinkWrap: widget.shrinkWrap ?? true,
      scrollDirection: widget.scrollDirection ?? Axis.vertical,
      itemBuilder: (context, index) {
        return draggableItem(context, index);
      },
      itemCount: dataList.length,
    );
  }


  // 生成可拖动的item
  Widget draggableItem(BuildContext context, int index) {
    T data = dataList[index];

    return LongPressDraggable(
      data: data,
      feedback: Transform(
        transform: Matrix4.identity()..scale(1.1, 1.1),
        alignment: Alignment.center,
        child: widget.itemBuilder(context, index, data),
      ),
      childWhenDragging: null,
      onDragStarted: () {
        setState(() {
          //记录开始拖拽的数据
          movingData = data;
        });
      },
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        setState(() {
          //清空标记进行重绘
          movingData = null;
        });
      },
      child: DragTarget<T>(
        builder: (context, candidateData, rejectedData) {
          return movingData == data ? Container() : widget.itemBuilder(context, index, data);
        },
        onWillAccept: (moveData) {
          var accept = moveData != null;
          if (accept) {
            exchangeItem(moveData, data);
          }
          return accept;
        },
        onAccept: (moveData) {
          movingData = null;
          exchangeItem(moveData, data);
        },
      ),
    );
  }

  // 重新排序
  void exchangeItem(T moveData, T toData) {
    setState(() {
      int toIndex = dataList.indexOf(toData);
      dataList.remove(moveData);
      dataList.insert(toIndex, moveData);
    });
    widget.onChanged(dataList);
  }

}

 多列表拖拽


import 'package:flutter/material.dart';


class DragGridView extends StatefulWidget {
  const DragGridView({super.key});

  @override
  State<StatefulWidget> createState() => _DragGridState();

}

class _DragGridState extends State<DragGridView> {

  Map<String, List<String>> data = {
    "List A" : ['A1', 'A2', 'A3', 'A4','A5','A6'],
    "List B" : ['B1', 'B2', 'B3', 'B4','B5','B6'],
  };

  String? movingValue;

  @override
  Widget build(BuildContext context) {
    List<Widget> children = [];

    data.forEach((key, list) {
      children.add(Text(key));
      children.add(GridView(
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              mainAxisSpacing: 5.0,
              crossAxisSpacing: 5.0,
              childAspectRatio: 1),
          physics: const NeverScrollableScrollPhysics(),
          shrinkWrap: true,
          children: buildItems(list)
      ));
      children.add(const SizedBox(height: 20,));
    });

    return Column(children: children);
  }

  // 生成GridView的items
  List<Widget> buildItems(List<String> list) {
    List<Widget> items = [];
    for (String title in list)  {
      items.add(Center(child: draggableItem(title),));
    }
    return items;
  }

  // 生成可拖动的item
  Widget draggableItem(String value) {
    return Draggable(
      data: value,
      feedback: baseItem(value),
      childWhenDragging: null,
      onDragStarted: () {
        setState(() {
          movingValue = value;//记录开始拖拽的数据
        });
      },
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        setState(() {
          movingValue = null;//清空标记进行重绘
        });
      },
      child: DragTarget(
        builder: (context, candidateData, rejectedData) {
          return baseItem(value);
        },
        onWillAccept: (moveData) {
          var accept = moveData != null;
          if (accept) {
            exchangeItem("$moveData", value, false);
          }
          return accept;
        },
        onAccept: (moveData) {
          exchangeItem("$moveData", value, true);
        },
      ),
    );
  }


  Widget baseItem(String value) {
    if (value == movingValue) {
      return Container();
    }
    return Container(
      width: 110,
      height: 110,
      color: Colors.blue,
      child: Center(
        child: Text(
          value,
          textAlign: TextAlign.center,
          style: const TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 20,
              color: Colors.yellowAccent),
        ),
      ),
    );
  }

  // 重新排序
  void exchangeItem(String moveData, String toData, bool onAccept) {
    setState(() {
      for (List<String> list in data.values) {
        if (list.contains(moveData)) {
          if (list.contains(toData)) {
            int toIndex = list.indexOf(toData);
            list.remove(moveData);
            list.insert(toIndex, moveData);
          } else {
            var toList = [];
            for (var value in data.values) {
              if (value.contains(toData)) {
                toList = value;
                break;
              }
            }
            int toIndex = toList.indexOf(toData);
            list.remove(moveData);
            toList.insert(toIndex, moveData);
          }
          break;
        }
      }

      if (onAccept) {
        movingValue = null;
      }
    });
  }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值