一统天下 flutter - widget 列表类: ReorderableListView - 可拖拽排序的列表

发布时间 2023-04-26 17:12:22作者: webabcd

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

一统天下 flutter - widget 列表类: ReorderableListView - 可拖拽排序的列表

示例如下:

lib\widget\list\reorderable_list_view.dart

/*
 * ReorderableListView - 可拖拽排序的列表
 */

import 'package:flutter/material.dart';

import '../../helper.dart';

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

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

class _ReorderableListViewDemoState extends State<ReorderableListViewDemo> {

  List<String> _dataList = [];

  @override
  void initState() {
    super.initState();

    _dataList = ['content1', 'content2', 'content3', 'content4', 'content5'];
  }

  Widget _getItem(String content) {
    return Container(
      /// 可拖拽的项必须要指定 key
      key: ValueKey(content),
      alignment: Alignment.center,
      margin: const EdgeInsets.all(2),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(10),
        color: Colors.blue,
      ),
      child: MyTextSmall(content),
    );
  }

  void _onReorder(int oldIndex, int newIndex) {
    log('onReorder, oldIndex:$oldIndex, newIndex:$newIndex');
    setState(() {
      /// 按照拖拽排序的结果重新排序数据源,并重新渲染
      var item = _dataList.removeAt(oldIndex);
      if (newIndex > oldIndex) {
        _dataList.insert(newIndex - 1, item);
      } else {
        _dataList.insert(newIndex, item);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("title"),),
      backgroundColor: Colors.orange,
      body: Column(
        children: [
          Expanded(
            child: ReorderableListView(
              /// 滚动方向 vertical 或 horizontal
              scrollDirection: Axis.vertical,
              /// header
              header: const MyText("header"),
              /// footer
              footer: const MyText("footer"),
              /// 内边距
              padding: EdgeInsets.zero,
              /// 是否反向排列
              reverse: false,
              /// 指定 ReorderableListView 关联的 ScrollController
              scrollController: null,
              /// 滚动到边缘时的物理效果,参见 /lib/widget/scroll/single_child_scroll_view.dart
              physics: const BouncingScrollPhysics(),
              /// 留白区域占可视区的百分比(0.0 - 1.0 之间)
              anchor: 0.0,
              /// 用于定义每个元素在滚动方向上的尺寸
              /// 也可以不指定这个,那么就由每个元素自己决定尺寸(注:建议使用 itemExtent 指定尺寸,这样性能会好一些)
              itemExtent: 40,

              /// 构造 ReorderableListView 中的每一项
              children: _dataList.map((e) => _getItem(e)).toList(),

              /// 拖拽排序操作完成后
              onReorder: _onReorder,
              /// 拖拽开始
              onReorderStart: (index) {
                log("onReorderStart:$index");
              },
              /// 拖拽结束
              onReorderEnd: (index) {
                log("onReorderEnd:$index");
              },
            ),
          ),

          /// 本例用于演示如何自定义拖拽行为,以及如何自定义拖拽中的项的样式
          /// 默认 android/ios 长按项后可拖拽,本例可以实现 android/ios 点击项后可拖拽
          Expanded(
            child: ReorderableListView(
              itemExtent: 40,
              onReorder: _onReorder,

              /// 禁用默认的拖拽行为
              buildDefaultDragHandles: false,
              /// 构造 ReorderableListView 中的每一项,并自定义其拖拽行为
              children: [
                for (int index = 0; index < _dataList.length; index++)
                  /// ReorderableDelayedDragStartListener - 长按项后即可拖拽
                  /// ReorderableDragStartListener - 点击项后即可拖拽
                  ReorderableDragStartListener (
                    key: ValueKey(_dataList[index]),
                    index: index,
                    child: Container(
                      alignment: Alignment.center,
                      margin: const EdgeInsets.all(2),
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.blue,
                      ),
                      child: MyTextSmall(_dataList[index]),
                    ),
                  ),
              ],

              /// 用于定义拖拽中的项的样式
              ///   child - 拖拽中的项
              ///   index - 拖拽中的项的索引位置
              proxyDecorator: (Widget child, int index, Animation<double> animation) {
                return Material(
                  child: Container(
                    decoration: const BoxDecoration(
                      color: Colors.red,
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(5),
                      child: child,
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

源码 https://github.com/webabcd/flutter_demo
作者 webabcd