Flutter ListView 拖拽排序瞭解一下

前面咱們對於 ListView 的操做講過 Flutter 滑動刪除最佳實踐,那如今咱們來了解一下 ListView 的拖拽排序。html

效果以下:api

ReorderableListView

想要達到如上效果,需使用該類,官網簡介:數組

A list whose items the user can interactively reorder by dragging.app

This class is appropriate for views with a small number of children because constructing the List requires doing work for every child that could possibly be displayed in the list view instead of just those children that are actually visible.ide

All children must have a key.函數

簡單翻譯以下:測試

用戶能夠經過拖動來從新排序的列表。ui

該類適用於少許 children 的頁面,由於構造列表須要爲每個 children 執行操做,而不僅是可見的 children。this

全部的 children 都必須有一個 key。spa

構造函數

按照慣例,查看構造函數:

ReorderableListView({
  this.header,
  @required this.children,
  @required this.onReorder,
  this.scrollDirection = Axis.vertical,
  this.padding,
  this.reverse = false,
}) : assert(scrollDirection != null),
assert(onReorder != null),
assert(children != null),
assert(
  children.every((Widget w) => w.key != null),
  'All children of this widget must have a key.',
);
複製代碼

瞭解一下各個參數:

  • header:是一個不參與拖動排序的 Widget
  • children:不用多說,列表項
  • onReorder:見名知意,從新排序後的回調
  • scrollDirection:方向

剩下兩個就很少說了,都應該瞭解。

簡單使用

既然看完了構造函數,那咱們就能夠分分鐘寫一個 Demo 出來:

class _ReorderableListViewPageState extends State<ReorderableListViewPage> {
  List<Color> _data = [
    Colors.blue,
    Colors.pinkAccent,
    Colors.deepPurple,
    Colors.orangeAccent
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ReorderableListViewPage'),
      ),
      body: ReorderableListView(
          header: Container(
            height: 50,
          ),
          children: _data
              .map((s) => Card(
                    color: s,
                    key: Key(s.toString()),
                    child: Container(
                      width: 300,
                      height: 100,
                    ),
                  ))
              .toList(),
          onReorder: (int oldIndex, int newIndex) {
            print("$oldIndex --- $newIndex");
          }),
    );
  }
}
複製代碼
  1. 首先咱們定義好一組顏色的列表
  2. 而後在 build 方法中返回 ReorderableListView
  3. ReorderableListView 中的 children 爲用顏色定義好的 Card
  4. onReorder 回調中打印兩個參數 oldIndex & newIndex

運行一下,看一下打印的 log:

能夠看到確實是能打印出新舊兩個 index, 可是這裏有一個很明顯的問題,

咱們你們都知道數組的下標是從 0 開始,能夠看到 第一次是 從 0 到 3,第二次是從 0 到 4,

可是講道理明明應該是 從 0 到 2,從 0 到 3。

那爲何我前兩次移動後的 newIndex 都 +1 了呢?

咱們這裏也不去深究,

既然咱們要移動,那確定也會對源數據進行操做,否則移動也都是假的。

因此,基於這樣的一個 newIndex,咱們只須要這樣:

setState(() {
  if(oldIndex < newIndex) {
  	newIndex -= 1;	
  }

  var temp = _data.removeAt(oldIndex);
  _data.insert(newIndex, temp);
});
複製代碼
  1. 先判斷是向上仍是向下拖拽
  2. 若是是向下拖拽,那麼 newIndex 會多加一個,咱們把它減掉
  3. 而後咱們刪除舊數據並保存它
  4. 最後在新的 index 上插入

ListView 的拖拽排序和刪除

既然前面說到了 ListView 的刪除,那這裏也必須把它倆組合起來了:

其實代碼很是簡單,固然這也得益於 Flutter 一切皆 Widget,咱們只須要在 Card 上包裹一個 Dismissible 就ok了:

children: _data
  .map((s) => Dismissible(
    key: Key("dismiss $s"),
    child: Card(
      color: s,
      key: Key(s.toString()),
      child: Container(
        width: 300,
        height: 100,
      ),
    ),
  ))
  .toList(),
複製代碼

總結

在 Flutter 當中,咱們能夠封裝不少的 Widget 來爲咱們往後的開發來節省時間,

固然,也不要忘記 Flutter 當中的 Widget 測試

相關文章
相關標籤/搜索