es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo mover elementos de lista sin tener que cambiar al modo de edición?

Actualmente, estoy construyendo una aplicación de lista de tareas pendientes en SwiftUI. Una característica que me gustaría implementar es la capacidad de ordenar su lista manualmente, por lo que he integrado la funcionalidad usando un modificador .onMove en mi bucle ForEach que llena mi List, pero todavía tuve que cambiar manualmente el EditMode, así que configuré el EditMode de la lista en .active de la siguiente manera:

import SwiftUI

struct ContentView: View {
@State private var items = ["1", "2", "3"]
@State var editMode: EditMode = .active

var body: some View {
    List {
        ForEach(items, id: \.self) { item in
            Text("Artículo \(item)")
        }
        .onMove(perform: { _, _  in })
    }
    .environment(\.editMode, $editMode)
}
}

Pero no estoy contento con esta implementación, ya que todavía tengo que usar el agarre del EditMode, y también rompe las SwipeActions y la funcionalidad de los botones.

Entonces, ¿cómo puedo mover elementos de la lista sin usar EditMode?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para mover elementos de lista sin utilizar EditMode, puedes crear tu propio gesto de arrastrar y aplicarlo a cualquier vista dentro de la Lista. Aquí tienes un ejemplo de implementación:

    1. En primer lugar, crea una variable de estado isDragging para realizar un seguimiento de si un elemento se está arrastrando o no:
      @State private var isDragging = false
      
    2. A continuación, modifica tu bucle ForEach para aplicar el gesto de arrastre a cada elemento:
      ForEach(items, id: \.self) { item in
         Text("Elemento \(item)")
             .gesture(DragGesture()
                 .onChanged { _ in
                     self.isDragging = true
                 }
                 .onEnded { _ in
                     self.isDragging = false
                 }
             )
      }
      
    3. Ahora puedes utilizar la variable de estado isDragging para cambiar la posición del elemento arrastrado. Sustituye el modificador .onMove por un modificador .listRowInsets que añade relleno a la fila cuando un elemento se está arrastrando:
      .listRowInsets(EdgeInsets(top: 0, leading: isDragging ? 50 : 15, bottom: 0, trailing: 15))
      

      Esto desplazará la fila hacia la derecha 50 puntos cuando se esté arrastrando un elemento, para que haya espacio para que el usuario lo suelte en una nueva posición.

    4. También necesitas modificar tu cierre .onEnded para actualizar el orden de tu array de items en función de la nueva posición del elemento arrastrado:

      .onEnded { value in
         let fromIndex = self.items.firstIndex(of: item)!
         let toIndex = self.items.firstIndex(where: { draggedItem in
             let from = self.index(for: fromIndex)
             let to = self.index(for: self.items.firstIndex(of: draggedItem)!)
             return from < to
         }) ?? self.items.endIndex - 1
      
         let removedItem = self.items.remove(at: fromIndex)
         self.items.insert(removedItem, at: toIndex)
      
         // Restablece el modo de edición
         self.editMode = .inactive
      }
      

      Este cierre se llama cuando finaliza el gesto de arrastre, pasando un parámetro value que representa el desplazamiento del arrastre. Puedes utilizar este desplazamiento para calcular la nueva posición del elemento arrastrado, y luego actualizar el orden de tu array de items en consecuencia.

    5. Por último, puedes eliminar el modificador environment(\.editMode, $editMode), ya que ya no lo necesitas para habilitar la funcionalidad de arrastrar y soltar.

    Con estos cambios, deberías poder mover elementos de la lista arrastrándolos sin utilizar EditMode, y sin interrumpir la funcionalidad de las SwipeActions o los botones.

Comments are closed.