如何在 SwiftUI 的列表中启用选择 [英] How does one enable selections in SwiftUI's List

查看:34
本文介绍了如何在 SwiftUI 的列表中启用选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 SwiftUI 创建一个简单的多选列表.我无法让它工作.

I am trying to create a simple multiple selection List with SwiftUI. I am unable to make it work.

List 接受第二个参数,它是一个 SelectionManager,所以我尝试创建一个的具体实现.但是,它永远不会被调用,行也不会突出显示.

List takes a second argument which is a SelectionManager, so I tried creating a concrete implementation of one. But, it never gets called and the rows never highlight.

import SwiftUI

var demoData = ["Phil Swanson", "Karen Gibbons", "Grant Kilman", "Wanda Green"]

struct SelectKeeper : SelectionManager{
    var selections = Set<UUID>()

    mutating func select(_ value: UUID) {
        selections.insert(value)
    }

    mutating func deselect(_ value: UUID) {
        selections.remove(value)
    }

    func isSelected(_ value: UUID) -> Bool {
        return selections.contains(value)
    }

    typealias SelectionValue = UUID

}

struct SelectionDemo : View {
    @State var selectKeeper = SelectKeeper()

    var body: some View {
        NavigationView {
            List(demoData.identified(by: .self)){ name in
                Text(name)
            }
                .navigationBarTitle(Text("Selection Demo"))
        }
    }
}

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

代码运行良好,但行没有突出显示,并且从不调用 SelectionManager 代码.

Code runs fine but rows don't highlight and the SelectionManager code is never called.

推荐答案

根据您的需求,有两种方法可以做到这一点:

Depending on what you want, there are two ways to do this:

您必须启用编辑模式";在选择之前的名单上很重要.从 List 的界面:

You must enable "Edit mode" on the list before a selection matters. From the interface for List:

    /// Creates an instance.
    ///
    /// - Parameter selection: A selection manager that identifies the selected row(s).
    ///
    /// - See Also: `View.selectionValue` which gives an identifier to the rows.
    ///
    /// - Note: On iOS and tvOS, you must explicitly put the `List` into Edit
    /// Mode for the selection to apply.
    @available(watchOS, unavailable)
    public init(selection: Binding<Selection>?, content: () -> Content)

您可以通过将 EditButton 添加到您的视图中的某处来实现.之后,你只需要为实现 SelectionManager 的东西绑定一个 var(你不需要在这里滚动你自己的:D)

You do that by adding an EditButton to your view somewhere. After that, you just need to bind a var for something that implements SelectionManager(you don't need to roll your own here :D)

var demoData = ["Phil Swanson", "Karen Gibbons", "Grant Kilman", "Wanda Green"]

struct SelectionDemo : View {
    @State var selectKeeper = Set<String>()
    
    var body: some View {
        NavigationView {
            List(demoData.identified(by: .self), selection: $selectKeeper){ name in
                Text(name)
            }
            .navigationBarItems(trailing: EditButton())
            .navigationBarTitle(Text("Selection Demo (selectKeeper.count)"))
        }
    }
}

这种方法看起来像这样:

This approach looks like this:

此时,我们将不得不推出自己的产品.注意:这个实现有一个错误,这意味着只有 Text 会导致选择发生.使用 Button 可以做到这一点,但由于 Beta 2 中删除了 borderlessButtonStyle() 的更改,它看起来很傻,我还没有想出解决方法.

At this point, we're going to have to roll our own. Note: this implementation has a bug which means that only the Text will cause a selection to occur. It is possible to do this with Button but because of the change in Beta 2 that removed borderlessButtonStyle() it looks goofy, and I haven't figured out a workaround yet.

struct Person: Identifiable, Hashable {
    let id = UUID()
    let name: String
}

var demoData = [Person(name: "Phil Swanson"), Person(name: "Karen Gibbons"), Person(name: "Grant Kilman"), Person(name: "Wanda Green")]

struct SelectKeeper : SelectionManager{
    var selections = Set<UUID>()
    
    mutating func select(_ value: UUID) {
        selections.insert(value)
    }
    
    mutating func deselect(_ value: UUID) {
        selections.remove(value)
    }
    
    func isSelected(_ value: UUID) -> Bool {
        return selections.contains(value)
    }
    
    typealias SelectionValue = UUID
    
}

struct SelectionDemo : View {
    @State var selectKeeper = Set<UUID>()
    
    var body: some View {
        NavigationView {
            List(demoData) { person in
                SelectableRow(person: person, selectedItems: self.$selectKeeper)
            }
            .navigationBarTitle(Text("Selection Demo (selectKeeper.count)"))
        }
    }
}

struct SelectableRow: View {
    var person: Person
    
    @Binding var selectedItems: Set<UUID>
    var isSelected: Bool {
        selectedItems.contains(person.id)
    }
    
    var body: some View {
        GeometryReader { geo in
            HStack {
                Text(self.person.name).frame(width: geo.size.width, height: geo.size.height, alignment: .leading)
            }.background(self.isSelected ? Color.gray : Color.clear)
            .tapAction {
                if self.isSelected {
                    self.selectedItems.remove(self.person.id)
                } else {
                    self.selectedItems.insert(self.person.id)
                }
            }
        }
    }
}

这篇关于如何在 SwiftUI 的列表中启用选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆