I'm trying to use draggable
in combination with dropDestination
to move around cells in a grid. Everything works except the animation in between drags.
struct PhotosGridViewDraggable: View {
@State var draggedItem: Color?
@State var colors: [Color] = [.red, .blue, .gray, .green, .pink, .yellow]
@Namespace var animation
var body: some View {
GeometryReader { proxy in
let hGap: CGFloat = 14
let width = proxy.size.width - (hGap * 2)
let cellWidth = (width / 3)
let cellSize = CGSize(width: cellWidth, height: cellWidth * 1.5)
let columns = [GridItem(.fixed(cellWidth)), GridItem(.fixed(cellWidth)), GridItem(.fixed(cellWidth))]
LazyVGrid(columns: columns) {
ForEach(colors.indices, id: \.self) { index in
let color = colors[index]
Rectangle()
.fill(color)
.frame(width: cellSize.width, height: cellSize.height)
.draggable(color, preview: {
RoundedRectangle(cornerRadius: 10)
.fill(.ultraThinMaterial)
.frame(width: 1, height: 1)
.onAppear {
draggedItem = color
}
})
.dropDestination(for: Color.self, action: { items, location in
return false
}, isTargeted: { status in
if let draggedItem = draggedItem, status, draggedItem != color {
if let sourceIndex = colors.firstIndex(of: draggedItem), let destinationIndex = colors.firstIndex(of: color) {
withAnimation { // PROBLEM: does nothing
let sourceItem = colors.remove(at: sourceIndex)
colors.insert(sourceItem, at: destinationIndex)
}
}
}
})
}
}
}
}
}
Expected:
Actual:
The id argument is configured to use the key .element, which means that the view uses the value of each element as a unique identifier for the view's elements. This means that if the elements in the colors array are unique, this will work correctly.
struct PhotosGridViewDraggable: View {
@State var draggedItem: Color?
@State var colors: [Color] = [.red, .blue, .gray, .green, .pink, .yellow]
@Namespace var animation
var body: some View {
GeometryReader { proxy in
let hGap: CGFloat = 14
let width = proxy.size.width - (hGap * 2)
let cellWidth = (width / 3)
let cellSize = CGSize(width: cellWidth, height: cellWidth * 1.5)
let columns = [GridItem(.fixed(cellWidth)), GridItem(.fixed(cellWidth)), GridItem(.fixed(cellWidth))]
LazyVGrid(columns: columns) {
ForEach(Array(colors.enumerated()), id: \.element) { index, color in
Rectangle()
.fill(color)
.frame(width: cellSize.width, height: cellSize.height)
.draggable(color, preview: {
RoundedRectangle(cornerRadius: 10)
.fill(.ultraThinMaterial)
.frame(width: 1, height: 1)
.onAppear {
draggedItem = color
}
})
.dropDestination(for: Color.self, action: { items, location in
return false
}, isTargeted: { status in
if let draggedItem = draggedItem, status, draggedItem != color {
if let sourceIndex = colors.firstIndex(of: draggedItem), let destinationIndex = colors.firstIndex(of: color) {
withAnimation {
let sourceItem = colors.remove(at: sourceIndex)
colors.insert(sourceItem, at: destinationIndex)
}
}
}
})
}
}
}
}
}