Сортируемый список с перетаскиванием по Flutter

Итак, я начинаю изучать Flutter и хотел бы использовать список перетаскивания в материальном дизайне, такой же, как на веб-сайте с рекомендациями по материалам.

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

Все библиотеки, которые я пробовал до сих пор, по сравнению с этим выглядят как мусор. Есть ли для этого хорошая библиотека, которой мне не хватает, или собственный виджет Flutter?


person Jared    schedule 23.12.2018    source источник


Ответы (5)


Проверьте knopp / flutter_reorderable_list. Это и достигается. Это действительно гладко, и у него нет проблем с производительностью, поскольку он может обрабатывать тысячи элементов.

Однако его реализация не так проста, как обычные виджеты флаттера.

Если вы боретесь с этим, я бы порекомендовал вам использовать созданный мной виджет для переноса flutter/ReorderableListViews в knopp/ReorderableList.

Этот виджет делает его действительно простым в использовании, однако он не обеспечивает такой гибкости, и, поскольку он работает с children List, он не такой масштабируемый, как оригинал.

Вот код для ReorderableListSimple, это демонстрация.

person Feu    schedule 24.12.2018
comment
Ваша версия отлично работала, спасибо. Я бы хотел, чтобы при переупорядочении каждой плитки было немного меньше лагов. Не знаю, будет ли в релизной версии плавнее. Также не могу понять, как настроить / убрать вибрацию при переупорядочивании. - person Jared; 25.12.2018
comment
Я также столкнулся с проблемой, когда, когда я делаю плитку списка закрываемой (flutter.io/docs/ поваренная книга / жесты / отключение) ручка не двигается, а остальная часть отодвигается, как должна. - person Jared; 25.12.2018
comment
Я знаю, что это не решение, но в своем приложении после некоторой борьбы я решил использовать режим переупорядочения. :( Итак, в режиме переупорядочивания я использую ReorderingList, и там есть дескриптор (и вы не можете делать ничего другого), а когда он не переупорядочивает, все остальное может делать пользователь. - person Feu; 25.12.2018
comment
Если вы используете ReorderingListSimple, возможно, вы могли бы использовать childrenAlreadyHaveListener = true, а затем вручную вставить ReorderableListener в ListTile и заставить его исчезнуть на Dismissible``s onRezize`! Сообщите мне, если это сработает !! Я знаю, что это не очень хорошо, но, возможно, это временное решение. - person Feu; 25.12.2018

введите описание изображения здесь

Для этого вы можете использовать собственный виджет флаттера ReorderableListView, вот пример этого.

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(() {});
      },
    ),
  );
}
person CopsOnRoad    schedule 23.06.2019
comment
Нажмите и удерживайте, чтобы изменить порядок - person Sondre Sørbye; 19.07.2019
comment
Просто деталь, насколько я понимаю, вам следует избегать пустых вызовов setState, и мне кажется, что весь код в onReorder может быть внутри вызова setState? - person UglyBob; 22.08.2019
comment
Обратите внимание, долгое нажатие для изменения порядка абсолютно нарушает спецификации материального дизайна и не должно использоваться на Android (понятия не имею о iOS). Насколько мне удалось выяснить до сих пор, нет способа предоставить дескрипторы, которые можно просто захватить с помощью ReorderableListView - person David Mulder; 12.09.2019
comment
@DavidMulder Вот как это реализовал Flutter, вы можете сообщить об ошибке на Github, указав проблему. - person CopsOnRoad; 12.09.2019
comment
@CopsOnRoad Собирался это сделать, но потом заметил, что на Flutter Github есть 5000 открытых проблем, и понял, что 1) публиковать там бессмысленно и 2) что я определенно не буду выполнять какую-либо производственную работу с флаттером ????. Так что да, просто хотел оставить это в стороне, так как это довольно важная вещь, которую нужно осознать, и это не так очевидно из изображения, которое вы включили. - person David Mulder; 12.09.2019
comment
Проблемы @DavidMulder 5000+ на самом деле не означают, что они будут решены в соответствии с шаблоном от самого старого до новейшего, вы можете публиковать любую обнаруженную ошибку, и вы должны получить ответ примерно в течение 24-48 часов. - person CopsOnRoad; 12.09.2019
comment
@DavidMulder и для будущих читателей: используйте долгое нажатие для изменения порядка, это абсолютно часть материального дизайна. См. material.io/design/interaction/gestures.html#types-of. -жеста. - person A. Bourgoin; 05.06.2020
comment
@ A.Bourgoin Это неверно, проверьте material.io/components/lists#behavior, чтобы изменить заказ элемент списка, перетащите его .. Длительное нажатие описано для блоков содержимого, а не списков (например, редактор, где обычное перетаскивание означает выделение) или элементов с четким маркером перетаскивания. - person David Mulder; 05.06.2020

Я пробовал flutter_reorderable_list и dragable_flutter_list, но ни один из них не работал должным образом - во время перетаскивания были некоторые нежелательные артефакты. Итак, я попытался найти собственное решение:

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,
          )
        ],
      );
    },
  );
}

Думаю, это не лучшее решение, и, возможно, я его изменю дальше, но пока оно работает достаточно хорошо

person Andrey Turkovsky    schedule 09.04.2019
comment
Вам следует попробовать pub.dev/packages/implicitly_animated_reorderable_list - person matteoh; 04.01.2021

Сам Flutter предоставляет класс ReorderableListView (Материал).

person jamesdlin    schedule 25.04.2019
comment
Вроде наделал немного бесполезной работы))) В общем, опыт был интересный. Жалко, что ReorderableListView не использует построитель, но я думаю, что использую его для своих нужд. Спасибо - person Andrey Turkovsky; 17.05.2019
comment
@AndreyTurkovsky ReorderableListView также имеет конструктор api.flutter.dev/flutter/material/ ReorderableListView / - person MSARKrish; 15.06.2021

Команда Flutter представила виджет ReorderableListView.

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

      ],
    )
person Benjith Kizhisseri    schedule 20.07.2019
comment
Имейте в виду, что в настоящее время отсутствуют некоторые функции, реализованные в ListView. Команда Flutter знает об этом, но все еще открыта для рекомендаций. Вы можете следить за этим здесь: github.com/flutter/flutter/issues/66080 - person Manu; 06.11.2020