I am trying to implement a swipe(from left to the right) to edit action using SwiftUI. A delete action(swipe from right to left) and a move item action works perfectly.
I want to open the edit screen on the left to the right guesture
This is my code:
struct TableView : View {
@State var dataSource = DataSource()
var body: some View {
NavigationView {
List {
ForEach(dataSource.pokemons.identified(by: \.id)) { pokemon in
Text(pokemon.name)
}
.onDelete(perform: deletePokemon)
.onMove(perform: movePokemon)
}
.navigationBarItems(leading: EditButton(), trailing: Button(action: addPokemon, label: { Text("Add") }))
.navigationBarTitle(Text("Pokemons"))
}
}
If you have configured a SwiftUI list view to support deletion or editing of its items, you can allow the user to toggle editing mode for your list view by adding an EditButton somewhere. When that is run, you'll find you can tap the edit button to enable or disable editing mode for the items in the list.
Probably the simplest way to build a list is to create a new SwiftUI view and wrap the Hello World text in a List: struct StaticListView: View { var body: some View { List { Text("Hello, world!") } } } To add more items to the list, we can just add another line: List { Text("Hello, world!") Text("Hello, SwiftUI!") }
Starting from iOS 15 you can use swipeActions
:
ForEach(dataSource.pokemons.identified(by: \.id)) { pokemon in
Text(pokemon.name)
}
.swipeActions(edge: .leading) {
Button("Edit") {
print("Edit")
}
.tint(.blue)
}
.swipeActions(edge: .trailing) {
Button("Delete", role: .destructive) {
print("Delete")
}
Button("Flag") {
print("Flag")
}
.tint(.orange)
}
I don't think it is possible currently.
The best suggestion I have is to roll your own solution by using UITableView
via the UIViewRepresentable
protocol. That being said, there might be viable open-source solutions out there.
I think hoping for all the UITableView
features you may want is risky because List
is supposed to be a "generic" type that is supported across various platforms. Some features of UITableView
may never come to a List
.
This is quick code I typed up, but it gives a simple example of how to create a custom UITableView
solution:
RoutineTableView(routines: routineDataSource.routines)
.trailingSwipeActionsConfiguration {
let editAction = UIContextualAction(
style: .normal,
title: "EDIT"
) { (action, sourceView, completionHandler) in
completionHandler(true)
}
editAction.backgroundColor = UIColor.darkGray
let deleteAction = UIContextualAction(
style: .destructive,
title: "DELETE"
) { (action, sourceView, completionHandler) in
completionHandler(true)
}
let actions = [deleteAction, editAction]
let configuration = UISwipeActionsConfiguration(actions: actions)
return configuration
}
.onCellPress {
print("hi there")
}
.navigationBarTitle("Routines")
private class CustomDataSource<SectionType: Hashable, ItemType: Hashable>: UITableViewDiffableDataSource<SectionType, ItemType> {
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
}
struct RoutineTableView: UIViewRepresentable {
let routines: [Routine]
private var onCellPress: (() -> Void)? = nil
private var trailingSwipeActionsConfiguration: (() -> UISwipeActionsConfiguration)? = nil
init(routines: [Routine]) {
self.routines = routines
}
func makeUIView(
context: UIViewRepresentableContext<RoutineTableView>
) -> UITableView {
let tableView = UITableView()
context.coordinator.update(withTableView: tableView)
return tableView
}
func updateUIView(_ uiView: UITableView, context: UIViewRepresentableContext<RoutineTableView>) {
context.coordinator.update(routines: routines)
}
// MARK: - Coordinator
func makeCoordinator() -> RoutineTableView.Coordinator {
return Coordinator(self)
}
class Coordinator: NSObject, UITableViewDelegate {
private enum Section {
case first
}
private let view: RoutineTableView
private var dataSource: UITableViewDiffableDataSource<Section, Routine>?
init(_ view: RoutineTableView) {
self.view = view
super.init()
}
func update(withTableView tableView: UITableView) {
tableView.register(RoutineTableViewCell.self)
tableView.delegate = self
let dataSource = CustomDataSource<Section, Routine>(tableView: tableView) { (tableView, indexPath, routine) -> UITableViewCell? in
let cell: RoutineTableViewCell = tableView.dequeueReusableCell(for: indexPath)
cell.configure(withRoutine: routine)
return cell
}
self.dataSource = dataSource
}
func update(routines: [Routine]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Routine>()
snapshot.appendSections([.first])
snapshot.appendItems(routines)
dataSource?.apply(snapshot, animatingDifferences: true)
}
// MARK: - <UITableViewDelegate>
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
view.onCellPress?()
}
func tableView(
_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration? {
return view.trailingSwipeActionsConfiguration?()
}
}
}
extension RoutineTableView {
func onCellPress(
_ onCellPress: @escaping () -> Void
) -> RoutineTableView {
var view = self
view.onCellPress = onCellPress
return view
}
func trailingSwipeActionsConfiguration(
_ trailingSwipeActionsConfiguration: @escaping () -> UISwipeActionsConfiguration
) -> RoutineTableView {
var view = self
view.trailingSwipeActionsConfiguration = trailingSwipeActionsConfiguration
return view
}
}
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