android lis分组拖拽,flutter-父子list的item拖动排序与合并

flutter多list拖动排序

背景

最近工作中开始从Android转到flutter,产品经理提了这样一个需求,

有2个list,每一个list都可以通过长按来拖动,重新排序里面item,同时还可以通过长按拖动操作将子item的内容填充到父list中,实现结果就是如下面这个gif所示,

a984d6ced566

list.gif

我从网上找了很多关于拖动排序的文章,发现几乎都是单个listview拖动排序的内容,用的就是插件ReorderableListView,我自己也实现了一个ReorderableListView来,发现它用于单个list拖动排序十分好用,但是如果是我遇到的2个list就无能为力了。网上也没有找到2个list拖动排序的内容,经过我自己对控件DragTarget和Draggable的学习,自己实现了一套2个list拖动的排序的代码,写下这篇文章来记录一下,如果有遇到同样问题的小伙伴可以参考一下。

先放上我借鉴的关于ReorderableListView,DragTarget和Draggable的文章链接,感谢他们的分享

代码

放上我写的主要的代码,

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

class TwoListDragSortPage extends StatefulWidget {

@override

State createState() {

// TODO: implement createState

return _TwoListDragSortState();

}

}

class _TwoListDragSortState extends State {

//伪造的数据,只是用于展示

//其中每一个list中都有一个最后一个空值,用于拖动能够拖动到最后一项

List leftList = ["数字", "汉字", "字母", "混合", ""];

List rightList = [

["1", "2", "3", "4", ""],

["发", "方式", "嘎阿尔", "人情味", ""],

["a", "b", "c", "d", ""],

["faga", "frety", "bnsh", "tqwv", ""]

];

int chooseIndex = 0;

@override

void initState() {

super.initState();

}

@override

Widget build(BuildContext context) {

// TODO: implement build

return Scaffold(

appBar: AppBar(

title: Text("双list排序"),

),

body: Container(

child: Row(

children: [

Flexible(

flex: 2,

child: ListView.separated(

itemBuilder: (context, index) {

return _getLeftWidget(index);

},

separatorBuilder: (context, index) {

if (index < leftList.length - 1) {

return Divider(

height: 1,

color: Colors.black87,

);

} else {

return Container();

}

},

itemCount: leftList.length)),

VerticalDivider(width: 2,color: Colors.white,),

Flexible(

flex: 5,

child: ListView.separated(

itemBuilder: (context, index) {

return _getRightWidget(index);

},

separatorBuilder: (context, index) {

if (index < rightList[chooseIndex].length - 1) {

return Divider(

height: 1,

color: Colors.black12,

);

} else {

return Container();

}

},

itemCount: rightList[chooseIndex].length)),

],

),

), // This trailing comma makes auto-formatting nicer for build methods.

);

}

Widget _getLeftItem(int index, bool isdrag) {

//list最后有一个空的item,是为了能够插入到最后一项目

if(index

return Container(

height: 30,

alignment: Alignment.centerLeft,

padding: EdgeInsets.only(left: 5),

color: isdrag

? Colors.black12

: index == chooseIndex

? Colors.orangeAccent

: Colors.black45,

child: Text(

leftList[index],

style: TextStyle(color: Colors.white, fontSize: 15),

),

);

}else{

return Container(

height: 30,

);

}

}

Widget _getLeftWidget(int index) {

//父list的每一个item是一个DragTarget可以接受数据

//也是一个LongPressDraggable可以被拖动

//同时也要有一个可以点击选中的状态

return InkWell(

onTap: () {

setState(() {

if (chooseIndex != index) {

chooseIndex = index;

}

});

},

child: DragTarget(

builder: (BuildContext context, List candidateData,

List rejectedData) {

if (candidateData.isNotEmpty && candidateData.first == 'aa') {

} else if (rejectedData.isNotEmpty) {

} else {}

return LongPressDraggable(

data: "${index}",

child: _getLeftItem(index, false), //默认子控件状态

feedback: _getLeftItem(index, true),//拖动时,拖动的状态

childWhenDragging: Container(), //拖动时,子控件的状态

);

},

onWillAccept: (s) {

return true;

},

onAccept: (s) {

//判断接受的数据,是子list拖动进入父list,还是父list自身排序

List list = (s as String).split("_");

if (list.length == 1) {

int newIndex = index;

int cuIndex = int.parse(list[0]);

moveLeftToleft(cuIndex, newIndex);

} else if (list.length == 2) {

int leftIndex = index;

int rightIndex = int.parse(list[1]);

moveRightToleft(leftIndex, rightIndex);

}

},

onAcceptWithDetails: (DragTargetDetails details) {

},

onLeave: (s) {

},

onMove: (DragTargetDetails details) {

},

),

);

}

Widget _getRigthItem(int index, bool isDrag) {

//list最后有一个空的item,是为了能够插入到最后一项目

if(index

return Container(

height: 50,

alignment: Alignment.centerLeft,

padding: EdgeInsets.only(left: 5, right: 5),

color: isDrag ? Colors.black12 : Colors.black45,

child: Text(

rightList[chooseIndex][index],

style: TextStyle(color: Colors.white, fontSize: 35),

),

);

}

else{

return Container(

height: 50,

);

}

}

Widget _getRightWidget(int index) {

//子list的每一个item是一个DragTarget可以接受数据

//也是一个LongPressDraggable可以被拖动

return DragTarget(

builder: (BuildContext context, List candidateData,

List rejectedData) {

if (candidateData.isNotEmpty) {

} else if (rejectedData.isNotEmpty) {

} else {}

return LongPressDraggable(

//这个地方,data我自己也有疑问,之前尝试过用list,

//发现接受不到list的数据,只能用String来表示是子list还是父list的item被拖动了

data: "${chooseIndex}_${index}",

child: _getRigthItem(index, false),

feedback: _getRigthItem(index, true),

childWhenDragging: Container(),

);

},

onWillAccept: (s) {

//判断接受的数据,只能接受子list中拖动排序

List list = (s as String).split("_");

if (list.length == 2) {

return true;

}

return false;

},

onAccept: (s) {

//只有onWillAccept返回值为true的时候才能接受到的数据

List list = (s as String).split("_");

if (list.length == 2) {

int newIndex = index;

int cuIndex = int.parse(list[1]);

moveRightToRight(cuIndex, newIndex);

}

},

onAcceptWithDetails: (DragTargetDetails details) {

},

onLeave: (s) {

},

onMove: (DragTargetDetails details) {

},

);

}

/**

* 父list的拖动排序

*/

void moveLeftToleft(int cuIndex,int newIndex){

if(cuIndex!=newIndex){

String str = leftList[cuIndex];

List list = rightList[cuIndex];

rightList.removeAt(cuIndex);

leftList.removeAt(cuIndex);

//根据拖动的位置,重新确定父list的数据

if(newIndex

leftList.insert(newIndex, str);

rightList.insert(newIndex, list);

}else{

leftList.insert(newIndex-1 , str);

rightList.insert(newIndex - 1, list);

}

//由于拖动的关系,父list的选中状态要重新结算位置

if(cuIndex==chooseIndex){

if(newIndex

chooseIndex = newIndex;

}else{

chooseIndex = newIndex - 1;

}

}

else if(chooseIndex>cuIndex&&chooseIndex

chooseIndex -= 1;

}

else if(chooseIndex>newIndex&&chooseIndex

chooseIndex += 1;

}

setState(() {

});

}

}

/**

* 子list的item拖动进入父list

*/

void moveRightToleft(int leftIndex,int rightIndex){

String str = rightList[chooseIndex][rightIndex];

rightList[chooseIndex].removeAt(rightIndex);

rightList[leftIndex].insert(rightList[leftIndex].length-1, str);

//如果某一个子list中的的item被移除完了,要删除它的父item

if(rightList[chooseIndex].length==1){

leftList.removeAt(chooseIndex);

chooseIndex = leftIndex;

}

setState(() {

});

}

/**

* 子list自己拖动排序

*/

void moveRightToRight(int cuIndex,int newIndex){

if(cuIndex!=newIndex){

String str = rightList[chooseIndex][cuIndex];

rightList[chooseIndex].removeAt(cuIndex);

if(newIndex

rightList[chooseIndex].insert(newIndex, str);

}else{

rightList[chooseIndex].insert(newIndex-1, str);

}

setState(() {

});

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值