SwiftUI - Custom Swipe Actions In List

后端 未结 3 715
一整个雨季
一整个雨季 2020-12-03 05:29

How can I use custom Swipe Actions in SwiftUI?

I tried to use the UIKit Framework to get these working in SwiftUI. But that doesn\'t work for me.

imp         


        
相关标签:
3条回答
  • 2020-12-03 05:46

    Based on Michał Ziobro answer using Introspect to simplify table view delegate setup.

    Note that this will override the table view delegate.

    struct ListSwipeActions: ViewModifier {
    
        @ObservedObject var coordinator = Coordinator()
    
        func body(content: Content) -> some View {
    
            return content
                .introspectTableView { tableView in
                    tableView.delegate = self.coordinator
                }
        }
    
        class Coordinator: NSObject, ObservableObject, UITableViewDelegate {
    
            func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
                return .delete
            }
    
            func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    
                let archiveAction = UIContextualAction(style: .normal, title: "Title") { action, view, completionHandler in
                    // update data source
                    completionHandler(true)
                }
                archiveAction.image = UIImage(systemName: "archivebox")!
                archiveAction.backgroundColor = .systemYellow
    
                let configuration = UISwipeActionsConfiguration(actions: [archiveAction])
    
                return configuration
            }
        }
    }
    
    extension List {
        func swipeActions() -> some View {
            return self.modifier(ListSwipeActions())
        }
    }
    
    0 讨论(0)
  • 2020-12-03 05:51

    It is able to be done in the way something like this:

               List {
                    ForEach(items) { (item) in
    
                        Text("\(item.title)")
                    }
                    .onDelete(perform: self.delete)
                }.swipeActions()
    

    Then you need to add this swipeActions() modifier

    struct ListSwipeActions: ViewModifier {
    
        @ObservedObject var coordinator = Coordinator()
    
        func body(content: Content) -> some View {
    
            return content
                .background(TableViewConfigurator(configure: { tableView in
                    delay {
                        tableView.delegate = self.coordinator
                    }
                }))
        }
    
        class Coordinator: NSObject, ObservableObject, UITableViewDelegate {
    
            func scrollViewDidScroll(_ scrollView: UIScrollView) {
                print("Scrolling ....!!!")
            }
    
            func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
                return .delete
            }
    
            func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    
                let isArchived = false
                let title = isArchived ? NSLocalizedString("Unarchive", comment: "Unarchive") : NSLocalizedString("Archive", comment: "Archive")
    
                let archiveAction = UIContextualAction(style: .normal, title: title, handler: {
                    (action, view, completionHandler) in
    
                    // update data source
                    completionHandler(true)
                })
                archiveAction.title = title
                archiveAction.image = UIImage(systemName: "archivebox")!
                archiveAction.backgroundColor = .systemYellow
    
                let configuration = UISwipeActionsConfiguration(actions: [archiveAction])
    
                return configuration
            }
        }
    }
    
    extension List {
    
        func swipeActions() -> some View {
            return self.modifier(ListSwipeActions())
        }
    }
    

    And have TableViewConfigurator that searches for table view behind the List

    struct TableViewConfigurator: UIViewControllerRepresentable {
    
        var configure: (UITableView) -> Void = { _ in }
    
        func makeUIViewController(context: Context) -> UIViewController {
    
            UIViewController()
        }
    
        func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    
    
            let tableViews = UIApplication.nonModalTopViewController()?.navigationController?.topViewController?.view.subviews(ofType: UITableView.self) ?? [UITableView]()
    
            for tableView in tableViews {
                self.configure(tableView)
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-03 05:57

    UPDATE

    As far as I can tell, the situation has not improved as of Xcode 12 beta 1 (released at WWDC 2020).

    ORIGINAL

    As of Xcode 11.3.1, SwiftUI doesn't support custom swipe actions for List items. Based on the history of Apple’s SDK evolution, we’re not likely to see support until the next major SDK version (at WWDC 2020) or later.

    You would probably be better off implementing a different user interface, like adding a toggle button as a subview of your list item, or adding a context menu to your list item.

    0 讨论(0)
提交回复
热议问题