El principio y el uso de Flutter Key (5) Un ejemplo que requiere una clave: una vista de lista que se puede arrastrar para cambiar el orden

El principio y uso de Flutter Key (1) Qué sucede sin Key

El principio y uso de Flutter Key (2) Correspondencia entre Widget y Element

El principio y uso de Flutter Key (3) Tres tipos de LocalKey

Principio y uso de Flutter Key (4) Uso de GlobalKey

El principio y el uso de Flutter Key (5) Un ejemplo que requiere una clave: una vista de lista que se puede arrastrar para cambiar el orden

Antes, presentamos varias claves en flutter, sus principios correspondientes y métodos de uso. Esta vez, revisemos y veamos un ejemplo que necesita usar claves.

ReorderableListViewReorderableListView

Probablemente haya usado ListViewel componente, que puede cambiar el tamaño, mostrar y desplazar una lista de elementos. Pero una cosa que no puede hacer es mover elementos en la lista. Afortunadamente, hay ReorderableListView.

ReorderableListViewNo es un componente de ListView de uso común. Es uno 用户可以通过拖动来重新排序其项目的列表组件. Con él, podemos moverlo en la dirección de desplazamiento de ListView manteniendo presionado el elemento y colocarlo en una nueva posición.

Tiene un requisito: todos los elementos de la lista deben tener una clave
y deben implementar onReorderel método, que es el método de devolución de llamada llamado por el usuario al reordenar la lista. Observe el efecto de no implementar esta devolución de llamada:

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

Se puede ver que aunque hemos intercambiado los cuadros rojo y verde, la interfaz de usuario no ha cambiado después de soltarlo, porque no se ha realizado onReorder.

onReorder: (oldIndex, newIndex), hay dos parámetros, oldIndex y newIndex, que representan el índice del widget arrastrado antes y después de arrastrarlo. Eche un vistazo a los resultados de impresión:

pasar de la posición 2 a la 1

La explicación es que se ha movido de la segunda posición a la primera posición (al principio es la posición 0). Cada vez que
ocurre un cambio de este tipo, debemos modificar el componente de la lista. Modificar
nuestro código y eliminar el widget de posición anterior. insértelo en la nueva ubicación:

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

Esto logra nuestro objetivo de mover el widget.
Pero de hecho, al mover el widget de arriba hacia abajo, hay un problema. Déjame moverlo de nuevo y echemos un vistazo:

asdasd.gif

Impresión correspondiente: Pasar de la posición 0 a la 2.
Solo mira el motivo:

índice artilugio
0 caja1
1 caja2
2 caja2

El orden que acabamos de mover es mover la caja 1 hacia atrás de la caja 2, que aquí se refleja de 0 a detrás de la caja 2, es decir, a la posición de 2, porque la posición de la caja 2 es 1. No sé si entiendes
Por supuesto, si te mueves desde la posición inicial hasta el final, se producirá un error de matriz fuera de los límites:

════════ 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)
════════════════════════════════════════════════════════════════════════════════════════════════════
 

Entonces, cuando nos movemos hacia abajo, tenemos que hacer un procesamiento adicional, el nuevo índice debe disminuirse en 1, y luego eliminarlo e insertarlo:

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

Lista horizontal, es decir, la operación a la derecha necesita ser procesada

Desventajas de ReorderableListView

Después de arrastrar varias veces, encontré varias deficiencias:

  • Mantenga presionado para activar el arrastre, fácil de tocar por error.
  • ReorderableListView sigue siendo una vista de lista, lo que significa que puede desplazarse. Cuando la lista es larga y se puede desplazar, habrá muchas operaciones incorrectas.
  • Para ListView unidimensional, todos sabemos que la vista de lista solo se puede deslizar en la dirección de desplazamiento, y lo mismo ocurre con ReorderableListView, que no se puede arrastrar hacia adelante y hacia atrás hacia arriba, hacia abajo, hacia la izquierda y hacia la derecha.

De hecho, podemos implementar dicho componente por nosotros mismos.
Si arrastramos, podemos Draggableimplementarlo a través de él. Es un widget que admite arrastrar y soltar.
Para evitar el desplazamiento, podemos usar Columny Row.

Cuando haya tiempo más tarde, se implementará un componente de lista que admite arrastrar para lograr mejor este efecto.

Supongo que te gusta

Origin blog.csdn.net/u011272795/article/details/120156732
Recomendado
Clasificación