当前位置:首页 » 《关注互联网》 » 正文

Flutter Key的原理和使用(五) 需要key的实例:可拖动改变顺序的Listview_卓原的进化之旅

28 人参与  2021年09月08日 12:23  分类 : 《关注互联网》  评论

点击全文阅读


Flutter Key的原理和使用(一) 没有Key会发生什么

Flutter Key的原理和使用(二) Widget 和 Element 的对应关系

Flutter Key的原理和使用(三) LocalKey的三种类型

Flutter Key的原理和使用(四) GlobalKey 的用法

Flutter Key的原理和使用(五) 需要key的实例:可拖动改变顺序的Listview

之前呢,我们介绍了flutter中的几种key,它们相应的原理和使用方式, 这次就来复习一下,看看一个需要用到key的实例.

ReorderableListView

你可能使用过ListView组件,它可以调整,显示和滚动项目列表. 但是不能做的一件事就是在列表中移动项目.幸运的是,有ReorderableListView.

ReorderableListView是不个不常用的ListView组件.它是一个用户可以通过拖动来重新排序其项目的列表组件. 有了它,我们可以通过长按项目来在ListView的滚动方向移动它,将其放在新的位置.

它有一个要求: 所有列表项都必须有一个Key
并且必须实现onReorder方法,它是用户在重新排序列表时调用的回调方法,看一下没有实现这个回调的效果:

ReorderableListView(
  children: [
    Box(Colors.blue, key: ValueKey(1)),
    Box(Colors.green, key: ValueKey(2)),
    Box(Colors.red, key: _globalKey),
  ],
  onReorder: (oldIndex, newIndex) {
    print('从位置$oldIndex移动到$newIndex');
  },
)

a.gif

可以看到虽然我们交换了红绿两个box,但是松手之后UI并没有变化,就是因为没有没有实现onReorder.

onReorder: (oldIndex, newIndex) , 分别有两个参数,oldIndex和newIndex, 它们代表的含义就是,拖动的widget拖动前和拖动后的index. 看一下打印结果:

从位置2移动到1

说明是从第2个位置移动到了第1个位置(最开始是第0的位置).
每当发生这样改变的时候,我们就需要把list组件修改.
修改一下我们的代码,移除旧位置的widget,在新的位置插入它:

final boxList = [
  Box(Colors.blue, key: ValueKey(1)),
  Box(Colors.green, key: ValueKey(2)),
  Box(Colors.red, key: ValueKey(3)),
];

Widget listWidget() {
  return ReorderableListView(
    children: boxList,
    onReorder: (oldIndex, newIndex) {
      print('从位置$oldIndex移动到$newIndex');
      final box = boxList.removeAt(oldIndex);
      boxList.insert(newIndex, box);
    },
  );
}

asd.gif

这样就达到了我们移动widget的目的.
但其实将widget从上向下移动的时候,有一个问题,我再移动一下大家看一下:

asdasd.gif

相应的打印: 从位置0移动到2.
简单看一下原因:

indexwidget
0box1
1box2
2box2

我们刚才移动的顺序是将box1移动到box2的后面 , 体现在这里就是从0移动到box2后面,也就是说是移动到了2的位置,因为box2的位置是1嘛. 不知道大家有没有理解.
当然了,如果从起始位置移动到最后,就会出现数组越界的报错:

════════ Exception caught by animation library ═════════════════════════════════════════════════════
The following RangeError was thrown while notifying status listeners for AnimationController:
Invalid value: Not in inclusive range 0..2: 3

When the exception was thrown, this was the stack: 
#0      List.insert (dart:core-patch/growable_array.dart:11:7)
#1      _MyHomePageState.listWidget.<anonymous closure> (package:flutter_key/home_page.dart:53:17)
#2      SliverReorderableListState._dropCompleted (package:flutter/src/widgets/reorderable_list.dart:646:24)
#3      _DragInfo._dropCompleted (package:flutter/src/widgets/reorderable_list.dart:1163:22)
#4      _DragInfo.startDrag.<anonymous closure> (package:flutter/src/widgets/reorderable_list.dart:1134:9)
...
The AnimationController notifying status listeners was: AnimationController#aca1a(⏮ 0.000; paused; DISPOSED)
════════════════════════════════════════════════════════════════════════════════════════════════════
 

所以在向下移动的时候,我们要额外处理一下,新的index要减1,之后再进行删除和插入操作:

if(newIndex>oldIndex){
  newIndex --;
}

横向列表,就是向右的操作要处理

ReorderableListView的缺点

在拖了几下之后,发现了几个缺点:

  • 长按才能触发拖动,容易误触.
  • ReorderableListView仍然是一个Listview,就是说它是会滚动的,当列表很长可以滚动的时候,会有很多误操作.
  • 一维的ListView,我们都知道listview只能在滚动方向来滑动,ReorderableListView也是一样,不能上下左右来回拖动.

其实我们可以通过自己来实现一个这样的组件.
拖动的话,我们可以通过Draggable来实现,它是一个支持拖拽的widget.
为了避免滚动.可以使用ColumnRow.

之后有时间, 会实现一个支持拖动的列表组件,来更好的实现这个效果.


点击全文阅读


本文链接:http://zhangshiyu.com/post/27328.html

拖动  位置  列表  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1