SwiftUI Button as EditButton
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
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
}
}
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.