SwiftUI Button as EditButton

2020-03-26 08:42发布

问题:

How I can use a button like EditButton?
Or how I can use a button to active edit mode from list?
Or how I can change the name from EditButton "edit" / "done"?

回答1:

The implementation below replaces EditButton's functionality with a Button:

import SwiftUI

struct ContentView: View {

    @State var isEditing = false
    @State var selection = Set<String>()

    var names = ["Karl", "Hans", "Faustao"]

    var body: some View {
        NavigationView {
            VStack {
                List(names, id: \.self, selection: $selection) { name in
                    Text(name)
                }
                .navigationBarTitle("Names")
                .environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive)).animation(Animation.spring())
                Button(action: {
                    self.isEditing.toggle()
                }) {
                    Text(isEditing ? "Done" : "Edit")
                        .frame(width: 80, height: 40)
                }
                .background(Color.yellow)
            }
            .padding(.bottom)
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

Result

However, by doing so, selection handling needs to be implemented by our own (which may or may not be an issue).

Unfortunately there isn't much documentation around that at this point: https://developer.apple.com/documentation/swiftui/list/3367016-init



回答2:

There is a better way to do this in Beta 5, where you can grab the @Environment binding directly (also better to make this a navigation bar item):

import SwiftUI

struct EditableListView: View {

    @State var items: [String] = ["1", "2", "3"]
    @State var selections: Set<String> = []

    @Environment(\.editMode) private var editMode: Binding<EditMode>

    var body: some View {
        List(items, id: \.self, selection: $selections) { item in
            Text(item)
        }
        .navigationBarItems(trailing:
            Button(action: {
                self.editMode?.value.toggle()
            }) {
                Text(self.editMode?.value == .active ? "Done" : "Edit")
            }
        )
        .animation(.default)
    }
}

extension EditMode {

    mutating func toggle() {
        self = self == .active ? .inactive : .active
    }
}



回答3:

Here's a way to preserve EditButton's functionality while still observing changes.

EditButton()
    .simultaneousGesture(TapGesture().onEnded {
        // Do your thing
    })

This works for every view on which you want to observe taps.