Jietu20230216-183433-HD
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
///一个列表,它允许从外部(按钮等)将数据拖入列表内,并且列表内的数据可以拖拽排序
class ListItemData<T extends Object> {
final int id;
final T value;
ListItemData(this.id, this.value);
}
class DropInList extends StatefulWidget {
const DropInList({super.key});
@override
State<StatefulWidget> createState() => _DropInListState();
}
class _DropInListState extends State<DropInList> {
final ScrollController scrollController = ScrollController();
List<ListItemData> list = [
ListItemData<String>(0, "A"),
ListItemData<String>(1, "B"),
ListItemData<String>(2, "C"),
ListItemData<String>(3, "D"),
ListItemData<String>(4, "E"),
];
ListItemData placeholder = ListItemData<String>(-1, "P");
ListItemData endData = ListItemData<String>(-2, "End");
@override
void initState() {
// TODO: implement initState
super.initState();
// list.add(endData);
}
@override
Widget build(BuildContext context) {
List<Widget> children = [];
for (int i = 0; i < list.length; i++) {
final data = list[i];
children.add(Container(
key: Key("${data.id}"),
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 4, top: 4),
child: cell(i, data),
));
}
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: Column(children: [
Expanded(
child: ReorderableListView(
scrollController: scrollController,
children: children,
onReorder: (int oldIndex, int newIndex) {
setState(() {
ListItemData data = list[oldIndex];
list.removeAt(oldIndex);
if (newIndex > oldIndex) {
list.insert(newIndex - 1, data);
} else {
list.insert(newIndex, data);
}
});
},
// prototypeItem: Container(child: Text("s"), color: Colors.red,),
proxyDecorator:
(Widget child, int index, Animation<double> animation) {
return cell(index, list[index]);
},
),
),
Container(
color: Colors.red,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
draggableItem("Add image", ListItemData(list.length, "Image")),
draggableItem("Add text", ListItemData(list.length, "Text")),
],
),
)
]),
),
);
}
int? curIndex;
Widget cell(int index, ListItemData data) {
if (data == placeholder) {
return Container(
height: 2,
color: Colors.red,
);
}
Widget child = Container(
height: 50,
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.lightBlue,
),
child: Text("${data.value}"),
);
if (data == endData) {
child = const SizedBox(
height: 20,
width: double.infinity,
);
}
if (curIndex == index) {
child = Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(children: [
Container(
width: 2,
height: 16,
color: Colors.greenAccent,
padding: const EdgeInsets.only(top: 8, bottom: 8),
),
],),
child,
],
);
}
return DragTarget<ListItemData>(
builder: (context, candidateData, rejectedData) {
return child;
},
onWillAccept: (moveData) {
if (kDebugMode) {
print("Cell_$index, data: ${data.value}");
}
setState(() {
curIndex = index;
});
return moveData != null;
},
onAccept: (moveData) {
if (kDebugMode) {
print("Cell_$index onAccept");
}
},
);
}
Widget draggableItem(String title, ListItemData data) {
return LongPressDraggable<ListItemData>(
data: data,
feedback: Material(
child: Transform(
transform: Matrix4.identity()..scale(1.1, 1.1),
alignment: Alignment.center,
child: Container(
width: 150,
height: 30,
color: Colors.red,
child: Text("${data.value}"),
),
),
),
childWhenDragging: null,
onDragStarted: () {
setState(() {
list.add(endData);
});
},
onDragEnd: (DraggableDetails details) {
setState(() {
if (curIndex != null) list.insert(curIndex!, data);
curIndex = null;
list.remove(endData);
});
},
onDraggableCanceled: (Velocity velocity, Offset offset) {
setState(() {
curIndex = null;
});
},
child: TextButton(onPressed: () {
setState(() {
list.add(data);
});
}, child: Text(title)),
);
}
}