如何在不使用swiftUI附带的幻灯片进行删除的情况下创建自定义删除按钮我不使用列表,仅使用foreach循环

时间:2020-09-10 06:47:07

标签: swiftui

由于onDelete和onMove是列表/表单的功能,如果没有它们的自定义界面,我将无法使用它们。我在ForEach中使用了VStack。对于swiftUI来说,我还很陌生,不确定如何实现onDelete和onMove的自定义代码。

这是我的代码:

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

它现在的工作方式:

enter image description here

3 个答案:

答案 0 :(得分:5)

这里是实现自定义删除的可能方法的简单演示(当然,通过拖放操作,由于拖放操作会更加复杂,但思路是相同的)。在Xcode 12 / iOS 14上进行了测试。

demo

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

答案 1 :(得分:1)

基于@Asperi的回答,我只是将其概括为接受任何ReDim Preserve Colcount(1 to a) 序列。

Equatable

}

答案 2 :(得分:0)

我最近需要删除一行,但我无法使用 LIST。相反,我有一个滚动视图......但我能够实现编辑来模拟相同的 onDelete 行为,就好像它是一个列表一样。最初我无法让我的代码工作。直到我仔细检查了我的实现并进行了实验,我才偶然发现了我的工作原理。我正在为 iPad 编码,所以我的 NavigationView 使用,

.navigationViewStyle(StackNavigationViewStyle())

一旦我将其添加到结构的 NavigationView,当您单击 EditButton 时,它会激活 editMode?.wrappedValue 到 .active / .inactive

下面是我对上面代码示例的实现...

struct Trying: View {
    
    @State var num: Int = 0
    @Environment(\.editMode) var editMode
    
    @State private var numbers = [0,1,2,3,4,5,6,7,8,9]
    var body: some View {
        NavigationView {

            VStack {
                ForEach(numbers, id: \.self) { number in
                    HStack {
                        if editMode?.wrappedValue == .active {
                            Button(action: { num = number
                                removeRows(numbr: num)
                            }, label: {
                                Image(systemName: "minus.circle.fill")
                                    .foregroundColor(.red)
                            })
                        } // END IF editMode?wrappedValue == .active
                        Text("\(number)")
                            .frame(width: 50, height: 50)
                            .background(Color.red)
                    }

                }
//                .onDelete(perform: removeRows)
            }

            .navigationTitle("Trying")
            .navigationBarItems(trailing: EditButton())
        }
        // FOR SOME REASON THIS ALLOWS THE EditButton() to activate editMode  without a LIST being present.
        .navigationViewStyle(StackNavigationViewStyle())
    }
    
    func removeRows(numbr: Int) {
        print("removing \(numbr)")
    }
}

看起来像:

EditMode Simulation