一統天下 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,
),
),
);
},
),
),
],
),
);
}
}