Since, the onDelete and onMove are features of List/form I cannot use them when I have custom interfaces without them. I have used a VStack inside a ForEach. I am quite new to swiftUI and unsure on how I can implement custom code for onDelete and onMove.
Here's my code:
struct Trying: View {
@State private var numbers = [0,1,2,3,4,5,6,7,8,9]
var body: some View {
NavigationView {
VStack (spacing: 10) {
ForEach(numbers, id: \.self) { number in
VStack {
Text("\(number)")
}
.frame(width: 50, height: 50)
.background(Color.red)
}.onDelete(perform: removeRows)
}
.navigationTitle("Trying")
.navigationBarItems(trailing: EditButton())
}
}
func removeRows(at offsets: IndexSet) {
numbers.remove(atOffsets: offsets)
}
}
The way it works right now:
Here is a simple demo of possible approach to implement custom delete (of course with move it would be more complicated due to drag/drop, but idea is the same). Tested with Xcode 12 / iOS 14.
struct DemoCustomDelete: View {
@State private var numbers = [0,1,2,3,4,5,6,7,8,9]
var body: some View {
NavigationView {
VStack (spacing: 10) {
ForEach(numbers, id: \.self) { number in
VStack {
Text("\(number)")
}
.frame(width: 50, height: 50)
.background(Color.red)
.overlay(
DeleteButton(number: number, numbers: $numbers, onDelete: removeRows)
, alignment: .topTrailing)
}.onDelete(perform: removeRows)
}
.navigationTitle("Trying")
.navigationBarItems(trailing: EditButton())
}
}
func removeRows(at offsets: IndexSet) {
withAnimation {
numbers.remove(atOffsets: offsets)
}
}
}
struct DeleteButton: View {
@Environment(\.editMode) var editMode
let number: Int
@Binding var numbers: [Int]
let onDelete: (IndexSet) -> ()
var body: some View {
VStack {
if self.editMode?.wrappedValue == .active {
Button(action: {
if let index = numbers.firstIndex(of: number) {
self.onDelete(IndexSet(integer: index))
}
}) {
Image(systemName: "minus.circle")
}
.offset(x: 10, y: -10)
}
}
}
}
Based on @Asperi's answer, I just generalized it to accept any Equatable
sequence.
struct DeleteButton<T>: View where T: Equatable {
@Environment(\.editMode) var editMode
let number: T
@Binding var numbers: [T]
let onDelete: (IndexSet) -> ()
var body: some View {
VStack {
if self.editMode?.wrappedValue == .active {
Button(action: {
if let index = numbers.firstIndex(of: number) {
self.onDelete(IndexSet(integer: index))
}
}) {
Image(systemName: "minus.circle")
}
.offset(x: 10, y: -10)
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With