Flutter
Flutter - ReorderableListView
대기만성 개발자
2020. 8. 12. 14:18
반응형
ListView를 사용할 때 순서를 바꿔야될 때 ReorderableListView를 사용하는데
children 부분이랑 onReorder부분을 처리하는게 생각보다 까다롭습니다
그래서 어떻게 하면 간단하게 할 수 있는지 알아보겠습니다
메인
class Reorderable extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ReorderableListview example')),
body: Consumer<ListItems>(
builder: (context, value, child) {
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) =>
value.updateList(oldIndex, newIndex),
children: value.getListItems
.map((item) => Card(
key: Key(item),
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
elevation: 8,
child: ListTile(
title: Text(item),
trailing: Icon(Icons.menu),
),
))
.toList());
},
),
);
}
}
ListItems
class ListItems extends ChangeNotifier {
List<String> _list = ['사과', '배', '바나나', '딸기'];
UnmodifiableListView<String> get getListItems {
return UnmodifiableListView(_list);
}
int get getLength {
return _list.length;
}
void updateList(int oldIndex, int newIndex) {
if (newIndex > getLength) {
newIndex = getLength;
}
if (oldIndex < newIndex) {
newIndex--;
}
String item = _list[oldIndex];
_list.remove(item);
_list.insert(newIndex, item);
notifyListeners();
}
}
newIndex가 list의 크기보다 커지면 에러가 발생하기 때문에
newIndex값이 더 커지면 length값을 할당해주고
oldIndex가 newIndex보다 작을때에 -1을 해주는것은
삽입되는 자리가 oldIndex값이 삭제되기 전의 자리이기 때문입니다
과정을 그림으로 보면 다음과 같습니다
ex) old = 1, new = 2인 경우
먼저 1번에서 index를 지정하고 oldIndex값이 삭제되고
newIndex자리에 값이 삽입이 됩니다
이 방법의 단점은 children 부분의 처리가 List를 Map으로 변환 후
다시 List로 변환하기때문에 크기가 커지면 성능상 문제가 있지않을까 생각됩니다
해결방안으로는 List.generate를 사용하는 방법이 있을거 같습니다
List.generate(value.getLength, (index){
String item = value.getListItems[index];
return Card(
key: Key(item),
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
elevation: 8,
child: ListTile(
title: Text(item),
trailing: Icon(Icons.menu),
),
);
})
그리고 ListTile을 longPress를 해서 drag and drop을 했을때에만 가능하고
trailing 아이콘부분은 다른방법을 통해 처리를 해줘야될거 같습니다
반응형