Flutter Sortable Drag And Drop ListView

好久不见. 提交于 2019-11-27 06:03:40

问题


So I'm starting to learn Flutter and would like to use a material design drag and drop list just like the one seen on the material guidelines website.

https://storage.googleapis.com/spec-host-backup/mio-design%2Fassets%2F1dtprsH4jZ2nOnjBCJeJXd7n4U-jmWyas%2F03-list-reorder.mp4

All of the libraries I have tried out so far look like garbage compared to that. Is there a good library for this that I am missing or a native Flutter widget?


回答1:


Check knopp/flutter_reorderable_list. It accomplishes just that. It's really smooth and it's got no performance issues, being able to handle thousands of items.

However, it's implementation is not easy as usual flutter widgets.

If you struggle with that, I'd recommend you to use a widget I created to port flutter/ReorderableListViews to the knopp/ReorderableList.

This widget makes it really easy to use, however it doesn't provide the same flexibility, and as it works with a children List, it's not as scalable as the original.

Here's the code for ReorderableListSimple and this is the demo.




回答2:


Flutter itself provides a (Material) ReorderableListView class.




回答3:


You can use native flutter widget, ReorderableListView to achieve it, here is the example of doing it.

List<String> _list = ["Apple", "Ball", "Cat", "Dog", "Elephant"];

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: ReorderableListView(
      children: _list.map((item) => ListTile(key: Key("${item}"), title: Text("${item}"), trailing: Icon(Icons.menu),)).toList(),
      onReorder: (int start, int current) {
        // dragging from top to bottom
        if (start < current) {
          int end = current - 1;
          String startItem = _list[start];
          int i = 0;
          int local = start;
          do {
            _list[local] = _list[++local];
            i++;
          } while (i < end - start);
          _list[end] = startItem;
        }
        // dragging from bottom to top
        else if (start > current) {
          String startItem = _list[start];
          for (int i = start; i > current; i--) {
            _list[i] = _list[i - 1];
          }
          _list[current] = startItem;
        }
        setState(() {});
      },
    ),
  );
}



回答4:


I've tried flutter_reorderable_list and dragable_flutter_list but none of them worked properly - there was some unwanted artifacts during dragging. So I've tried to make own solution:

ListView.builder(
  itemBuilder: (context, index) => buildRow(index),
  itemCount: trackList.length,
),

Widget buildRow(int index) {
  final track = trackList[index];
  ListTile tile = ListTile(
    title: Text('${track.getName()}'),
  );
  Draggable draggable = LongPressDraggable<Track>(
    data: track,
    axis: Axis.vertical,
    maxSimultaneousDrags: 1,
    child: tile,
    childWhenDragging: Opacity(
      opacity: 0.5,
      child: tile,
    ),
    feedback: Material(
      child: ConstrainedBox(
        constraints:
            BoxConstraints(maxWidth: MediaQuery.of(context).size.width),
        child: tile,
      ),
      elevation: 4.0,
    ),
  );

  return DragTarget<Track>(
    onWillAccept: (track) {
      return trackList.indexOf(track) != index;
    },
    onAccept: (track) {
      setState(() {
        int currentIndex = trackList.indexOf(track);
        trackList.remove(track);
        trackList.insert(currentIndex > index ? index : index - 1, track);
      });
    },
    builder: (BuildContext context, List<Track> candidateData,
        List<dynamic> rejectedData) {
      return Column(
        children: <Widget>[
          AnimatedSize(
            duration: Duration(milliseconds: 100),
            vsync: this,
            child: candidateData.isEmpty
                ? Container()
                : Opacity(
                    opacity: 0.0,
                    child: tile,
                  ),
          ),
          Card(
            child: candidateData.isEmpty ? draggable : tile,
          )
        ],
      );
    },
  );
}

I guess, this is not the best solution, and I'm maybe will change it further, but for now it works quite well




回答5:


Flutter team introduced ReorderableListView widget.

ReorderableListView(
      children: <Widget>[
        for (var item in appState.menuButtons) 
        Text('data')              

      ],
    )


来源:https://stackoverflow.com/questions/53908025/flutter-sortable-drag-and-drop-listview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!