Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Button as EditButton

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"?

like image 435
Aiiboo Avatar asked Aug 04 '19 06:08

Aiiboo


4 Answers

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.

like image 178
Valentin Walter Avatar answered Oct 27 '22 10:10

Valentin Walter


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

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

like image 25
backslash-f Avatar answered Oct 27 '22 10:10

backslash-f


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

EditableListAnimation

like image 6
Procrastin8 Avatar answered Oct 27 '22 10:10

Procrastin8


As for Xcode 13, there seems to be some update. I test the following code works.

@State var editMode: EditMode = .inactive
@State var isEditing = false

List {
.....
}.environment(\.editMode, $editMode)

Button(action: {
isEditing.toggle()
editMode = isEditing ? .active : .inactive
})
like image 3
luomein Avatar answered Oct 27 '22 12:10

luomein