Flutter可重排序列表插件vietmap_reorderable_list的使用
Flutter可重排序列表插件vietmap_reorderable_list的使用
一个简单的包用于创建可重排序的列表。
示例代码
import 'package:flutter/material.dart' hide ReorderableListView;
import 'package:intl/intl.dart';
import 'package:vietmap_reorderable_list/widgets/vietmap_reorderable_list.dart';
void main() => runApp(const ReorderableApp());
class ReorderableApp extends StatelessWidget {
const ReorderableApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('可重排序列表示例')),
body: const ReorderableExample(),
),
);
}
}
class MockData {
final String name;
final int timeStamp;
MockData({required this.name, required this.timeStamp});
}
class ReorderableExample extends StatefulWidget {
const ReorderableExample({super.key});
@override
State<ReorderableExample> createState() => _ReorderableListViewExampleState();
}
class _ReorderableListViewExampleState extends State<ReorderableExample> {
final List<int> _items = List<int>.generate(50, (int index) => index);
List<GlobalKey> itemKeys = [];
ScrollController scrollController = ScrollController();
final List<MockData> data = [
MockData(name: '项目 1', timeStamp: 1710992339000),
MockData(name: '项目 2', timeStamp: 1710993339000),
MockData(name: '项目 3', timeStamp: 1710994339000),
MockData(name: '项目 4', timeStamp: 1710995339000),
MockData(name: '项目 5', timeStamp: 1710996339000),
MockData(name: '项目 6', timeStamp: 1710997339000),
MockData(name: '项目 7', timeStamp: 1710998339000),
MockData(name: '项目 8', timeStamp: 1710999339000),
MockData(name: '项目 9', timeStamp: 1711000339000),
MockData(name: '项目 10', timeStamp: 1711001339000),
MockData(name: '项目 11', timeStamp: 1711002339000),
MockData(name: '项目 12', timeStamp: 1711003339000),
MockData(name: '项目 13', timeStamp: 1711004339000),
MockData(name: '项目 14', timeStamp: 1711005339000),
MockData(name: '项目 15', timeStamp: 1711006339000),
MockData(name: '项目 16', timeStamp: 1711007339000),
MockData(name: '项目 17', timeStamp: 1711008339000),
MockData(name: '项目 18', timeStamp: 1711009339000),
MockData(name: '项目 19', timeStamp: 1711010339000),
MockData(name: '项目 20', timeStamp: 1711011339000),
MockData(name: '项目 21', timeStamp: 1711012339000),
MockData(name: '项目 22', timeStamp: 1711013339000),
MockData(name: '项目 23', timeStamp: 1711014339000),
MockData(name: '项目 24', timeStamp: 1711015339000),
MockData(name: '项目 25', timeStamp: 1711016339000),
MockData(name: '项目 26', timeStamp: 1711017339000),
MockData(name: '项目 27', timeStamp: 1711018339000),
MockData(name: '项目 28', timeStamp: 1711019339000),
MockData(name: '项目 29', timeStamp: 1711020339000),
MockData(name: '项目 30', timeStamp: 1711021339000),
MockData(name: '项目 31', timeStamp: 1711022339000),
MockData(name: '项目 32', timeStamp: 1711023339000),
MockData(name: '项目 33', timeStamp: 1711024339000),
MockData(name: '项目 34', timeStamp: 1711025339000),
MockData(name: '项目 35', timeStamp: 1711026339000),
MockData(name: '项目 36', timeStamp: 1711027339000),
MockData(name: '项目 37', timeStamp: 1711028339000),
MockData(name: '项目 38', timeStamp: 1711029339000),
MockData(name: '项目 39', timeStamp: 1711030339000),
MockData(name: '项目 40', timeStamp: 1711031339000),
MockData(name: '项目 41', timeStamp: 1711032339000),
MockData(name: '项目 42', timeStamp: 1711033339000),
MockData(name: '项目 43', timeStamp: 1711034339000),
MockData(name: '项目 44', timeStamp: 1711035339000),
MockData(name: '项目 45', timeStamp: 1711036339000),
MockData(name: '项目 46', timeStamp: 1711037339000),
MockData(name: '项目 47', timeStamp: 1711038339000),
MockData(name: '项目 48', timeStamp: 1711039339000),
MockData(name: '项目 49', timeStamp: 1711040339000),
MockData(name: '项目 50', timeStamp: 1711041339000),
];
@override
void initState() {
scrollController.addListener(() {
// print('+++++++++++++++++++++++++++++++++++++++++');
// print(scrollController.position.pixels);
});
super.initState();
}
@override
Widget build(BuildContext context) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
final Color oddItemColor = colorScheme.primary.withOpacity(0.05);
final Color evenItemColor = colorScheme.primary.withOpacity(0.15);
return Container(
color: Colors.red.withOpacity(0.2),
child: Stack(
children: [
Positioned(
top: 0,
left: 95,
child: Container(
width: 5,
height: MediaQuery.sizeOf(context).height,
color: Colors.red,
),
),
VietmapReorderableListView(
scrollController: scrollController,
padding: const EdgeInsets.symmetric(horizontal: 40),
onReorderStart: (index) {
// print('-----------------zzz');
},
children: List.generate(50, (index) {
itemKeys.add(GlobalKey());
return Listener(
onPointerMove: (event) {
// print(event.position.dy);
// print('-----------------Pointer Move-----------------');
},
key: itemKeys[index],
// onVerticalDragUpdate: (details) {
// print('---------------d-----------------');
// },
child: ListTile(
contentPadding: EdgeInsets.zero,
tileColor: Colors.transparent,
leading: Text(formatTime(data[index].timeStamp)),
title: Container(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 15),
decoration: BoxDecoration(
color:
_items[index].isOdd ? oddItemColor : evenItemColor,
),
child: Text('项目 ${_items[index]}')),
),
);
}),
onReordering: (index, dragIndex) {
print('-----------------reordering$index, $dragIndex');
MockData nearestTopData = data[dragIndex - 2];
MockData currentData = data[dragIndex - 1];
MockData nearestBottomData = data[dragIndex];
// print(nearestTopData.name);
// print(currentData.name);
// print(nearestBottomData.name);
// print('----------------------------------');
// print(_getPosition(dragIndex - 2));
// print(_getPosition(dragIndex - 1));
// print(_getPosition(dragIndex));
// print('--------------------enda--------------');
// print(nearestTopData.timeStamp);
// print(nearestBottomData.timeStamp);
},
onReorderEnd: (index) {
// print('-----------------end');
},
onReorder: (int oldIndex, int newIndex) {
setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final int item = _items.removeAt(oldIndex);
_items.insert(newIndex, item);
data.insert(newIndex, data.removeAt(oldIndex));
});
},
),
],
),
);
}
double _getPosition(int index) {
RenderBox box =
itemKeys[index].currentContext!.findRenderObject() as RenderBox;
Offset currentPosition =
box.localToGlobal(Offset.zero); //this is global position
double y = currentPosition.dy; //this is y - I think it's what you want
return y;
}
String formatTime(int timeStamp) {
return DateFormat('HH:mm aa')
.format(DateTime.fromMillisecondsSinceEpoch(timeStamp));
}
}
代码解释
-
导入必要的库:
import 'package:flutter/material.dart' hide ReorderableListView; import 'package:intl/intl.dart'; import 'package:vietmap_reorderable_list/widgets/vietmap_reorderable_list.dart';
-
定义主应用类
ReorderableApp
:class ReorderableApp extends StatelessWidget { const ReorderableApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('可重排序列表示例')), body: const ReorderableExample(), ), ); } }
-
定义数据模型
MockData
:class MockData { final String name; final int timeStamp; MockData({required this.name, required this.timeStamp}); }
-
定义状态管理类
_ReorderableListViewExampleState
:class _ReorderableListViewExampleState extends State<ReorderableExample> { final List<int> _items = List<int>.generate(50, (int index) => index); List<GlobalKey> itemKeys = []; ScrollController scrollController = ScrollController(); final List<MockData> data = [ // 数据项 ];
-
初始化状态并监听滚动事件:
@override void initState() { scrollController.addListener(() { // print('+++++++++++++++++++++++++++++++++++++++++'); // print(scrollController.position.pixels); }); super.initState(); }
-
构建UI:
@override Widget build(BuildContext context) { final ColorScheme colorScheme = Theme.of(context).colorScheme; final Color oddItemColor = colorScheme.primary.withOpacity(0.05); final Color evenItemColor = colorScheme.primary.withOpacity(0.15); return Container( color: Colors.red.withOpacity(0.2), child: Stack( children: [ Positioned( top: 0, left: 95, child: Container( width: 5, height: MediaQuery.sizeOf(context).height, color: Colors.red, ), ), VietmapReorderableListView( scrollController: scrollController, padding: const EdgeInsets.symmetric(horizontal: 40), onReorderStart: (index) { // print('-----------------zzz'); }, children: List.generate(50, (index) { itemKeys.add(GlobalKey()); return Listener( onPointerMove: (event) { // print(event.position.dy); // print('-----------------Pointer Move-----------------'); }, key: itemKeys[index], child: ListTile( contentPadding: EdgeInsets.zero, tileColor: Colors.transparent, leading: Text(formatTime(data[index].timeStamp)), title: Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 15), decoration: BoxDecoration( color: _items[index].isOdd ? oddItemColor : evenItemColor, ), child: Text('项目 ${_items[index]}')), ), ); }), onReordering: (index, dragIndex) { print('-----------------reordering$index, $dragIndex'); // 处理重新排序逻辑 }, onReorderEnd: (index) { // print('-----------------end'); }, onReorder: (int oldIndex, int newIndex) { setState(() { if (oldIndex < newIndex) { newIndex -= 1; } final int item = _items.removeAt(oldIndex); _items.insert(newIndex, item); data.insert(newIndex, data.removeAt(oldIndex)); }); }, ), ], ), ); }
-
获取元素位置:
double _getPosition(int index) { RenderBox box = itemKeys[index].currentContext!.findRenderObject() as RenderBox; Offset currentPosition = box.localToGlobal(Offset.zero); //this is global position double y = currentPosition.dy; //this is y - I think it's what you want return y; }
-
格式化时间戳:
String formatTime(int timeStamp) { return DateFormat('HH:mm aa') .format(DateTime.fromMillisecondsSinceEpoch(timeStamp)); }
更多关于Flutter可重排序列表插件vietmap_reorderable_list的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter可重排序列表插件vietmap_reorderable_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
vietmap_reorderable_list
是一个用于 Flutter 的可重排序列表插件,它允许用户通过拖拽来重新排序列表中的项目。这个插件非常适合需要用户自定义列表顺序的应用场景。
安装
首先,你需要在 pubspec.yaml
文件中添加依赖:
dependencies:
vietmap_reorderable_list: ^1.0.0
然后运行 flutter pub get
来安装插件。
基本用法
下面是一个简单的示例,展示了如何使用 vietmap_reorderable_list
来创建一个可重排序的列表。
import 'package:flutter/material.dart';
import 'package:vietmap_reorderable_list/vietmap_reorderable_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ReorderableListExample(),
);
}
}
class ReorderableListExample extends StatefulWidget {
@override
_ReorderableListExampleState createState() => _ReorderableListExampleState();
}
class _ReorderableListExampleState extends State<ReorderableListExample> {
List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Reorderable List Example'),
),
body: VietMapReorderableList(
children: items.map((item) {
return ListTile(
key: Key(item),
title: Text(item),
);
}).toList(),
onReorder: (oldIndex, newIndex) {
setState(() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final item = items.removeAt(oldIndex);
items.insert(newIndex, item);
});
},
),
);
}
}
代码解释
-
依赖导入:首先导入
vietmap_reorderable_list
插件。 -
状态管理:使用
StatefulWidget
来管理列表的状态。items
是一个字符串列表,表示列表中的项目。 -
VietMapReorderableList
组件:这是一个核心组件,用于创建可重排序的列表。它接受两个主要参数:children
:列表中的项目,通常是一个List<Widget>
。onReorder
:当用户拖拽项目并重新排序时触发的回调函数。oldIndex
是项目原来的位置,newIndex
是项目将要移动到的位置。
-
onReorder
回调:在onReorder
回调中,我们更新items
列表的顺序。首先,我们根据oldIndex
和newIndex
调整项目的顺序,然后调用setState
来更新 UI。
自定义样式
你可以根据需要自定义列表项的样式。例如,可以给 ListTile
添加图标、背景颜色等。
ListTile(
key: Key(item),
title: Text(item),
leading: Icon(Icons.drag_handle),
tileColor: Colors.grey[200],
)