Never give up

Flutter - ReorderableListView 본문

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 아이콘부분은 다른방법을 통해 처리를 해줘야될거 같습니다

반응형
Comments