我如何识别第二个'点击Swiftui中的分段控件?

发布于 2025-01-24 22:16:04 字数 2443 浏览 4 评论 0原文

在Swiftui中,我有一个带有。分段样式的选择器,我用来选择列表的排序方式。我想要的是,除了正常行为之外 以下是标题中具有分段控件的列表的示例,用于更改该列表的排序方式:

struct ContentView: View {
    @State private var animals = [
        Animal(name: "Lion", number: 1),
        Animal(name: "Monkey", number: 2),
        Animal(name: "Elephant", number: 3),
    ]
    @State private var sortOrder: SortOrder = .alphabetical

    var body: some View {
        List {
            Section {
                ForEach(animals) { animal in
                    HStack {
                        Text(animal.name)
                        Spacer()
                        Text("\(animal.number)")
                    }
                }
            } header: {
                VStack(alignment: .leading, spacing: 0) {
                    Text("Sort:")
                    HStack {
                        Picker("Sorting methods", selection: $sortOrder) {
                            ForEach(SortOrder.allCases, id: \.self) { sortOrder in
                                Text(sortOrder.description)
                            }
                        }
                        .pickerStyle(.segmented)
                    }
                }
                .onChange(of: sortOrder) { sortOrder in
                    withAnimation {
                        sort(by: sortOrder)
                    }
                }
                .onAppear() {
                    sort(by: self.sortOrder)
                }
            }
        }
        .listStyle(.inset)
    }

    private func sort(by sortOrder: SortOrder) {
        switch sortOrder {
            case .alphabetical: return animals.sort(by: { $0.name < $1.name })
            case .numerical:    return animals.sort(by: { $0.number < $1.number })
        }
    }
}

struct Animal: Identifiable {
    var id = UUID()
    var name: String
    var number: Int
}

enum SortOrder: CaseIterable {
    case alphabetical
    case numerical

    var description: String {
        switch self {
            case .alphabetical: return "Alphabetical"
            case .numerical:    return "Numerical"
        }
    }
}

这一切都很好:列表按名称或数字进行排序。我现在想要的是通过点击所选段再次来扭转排序顺序。因此,例如,通过首次敲击段“字母数字”,该列表被排序了AZ。我想在同一段上进行第二次点击以对za进行排序。数字排序类似。
不幸的是,我没有收到任何通知,即第二次被挖掘。我尝试使用.ontapgesture,但是a)干扰了普通的选择器行为,而b)仅指定picker上的 ,但不是哪个段轻拍。
我想我可以制作自己的自定义选择器,但我正在努力避免这种情况,因为Swiftui的Picker否则做得很好。除了第二次点击,也就是说。 :-)。
任何想法/建议都将受到高度赞赏。谢谢!

In SwiftUI, I have a Picker with a .segmented style that I use to select how a list is sorted. What I want is for each segment of that picker to reverse the sort order, in addition to its normal behaviour.
Below is an example of a list with a segmented control in the header that is used to change how such a list can be sorted:

struct ContentView: View {
    @State private var animals = [
        Animal(name: "Lion", number: 1),
        Animal(name: "Monkey", number: 2),
        Animal(name: "Elephant", number: 3),
    ]
    @State private var sortOrder: SortOrder = .alphabetical

    var body: some View {
        List {
            Section {
                ForEach(animals) { animal in
                    HStack {
                        Text(animal.name)
                        Spacer()
                        Text("\(animal.number)")
                    }
                }
            } header: {
                VStack(alignment: .leading, spacing: 0) {
                    Text("Sort:")
                    HStack {
                        Picker("Sorting methods", selection: $sortOrder) {
                            ForEach(SortOrder.allCases, id: \.self) { sortOrder in
                                Text(sortOrder.description)
                            }
                        }
                        .pickerStyle(.segmented)
                    }
                }
                .onChange(of: sortOrder) { sortOrder in
                    withAnimation {
                        sort(by: sortOrder)
                    }
                }
                .onAppear() {
                    sort(by: self.sortOrder)
                }
            }
        }
        .listStyle(.inset)
    }

    private func sort(by sortOrder: SortOrder) {
        switch sortOrder {
            case .alphabetical: return animals.sort(by: { $0.name < $1.name })
            case .numerical:    return animals.sort(by: { $0.number < $1.number })
        }
    }
}

struct Animal: Identifiable {
    var id = UUID()
    var name: String
    var number: Int
}

enum SortOrder: CaseIterable {
    case alphabetical
    case numerical

    var description: String {
        switch self {
            case .alphabetical: return "Alphabetical"
            case .numerical:    return "Numerical"
        }
    }
}

This all works fine: the list gets sorted by name or by number. What I want now is to reverse the sort order by tapping on a selected segment again. So for example, by tapping on segment 'alphanumeric' for the first time, the list is sorted A-Z. I want a second tap on that same segment to sort Z-A. Similar for numeric sorting.
Unfortunately, I don't get any notification that a segment is tapped for a second time. I tried using .onTapGesture, but that a) interferes with the normal picker behaviour and b) only specifies that there was a tap somewhere on the picker, but not which segment was tapped.
I guess I could make my own custom picker, but I am trying to avoid that, because SwiftUI's picker does a great job otherwise. Except for the second tap, that is. :-).
Any ideas/suggestions are highly appreciated. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

熟人话多 2025-01-31 22:16:04

尝试这样的事情,并在选择器按钮上进行双重点击:

struct ContentView: View {
    @State private var animals = [
        Animal(name: "Lion", number: 1),
        Animal(name: "Monkey", number: 2),
        Animal(name: "Elephant", number: 3),
    ]
    @State var sortOrder: SortOrder = .alphabetical
    @State var sortReverse = false  // <-- here
    
    var body: some View {
        List {
            Section {
                ForEach(animals) { animal in
                    HStack {
                        Text(animal.name)
                        Spacer()
                        Text("\(animal.number)")
                    }
                }
            } header: {
                VStack(alignment: .leading, spacing: 0) {
                    Text("Sort:")
                    HStack {
                        Picker("Sorting methods", selection: $sortOrder) {
                            ForEach(SortOrder.allCases, id: \.self) { sortOrder in
                                Text(sortOrder.description)
                            }
                        }
                        .onTapGesture(count: 2) { // <-- here
                            sortReverse.toggle()
                            sort(by: sortOrder)
                        }
                        .pickerStyle(.segmented)
                    }
                }
                .onChange(of: sortOrder) { sortOrder in
                    withAnimation {
                        sortReverse = false  // <-- here
                        sort(by: sortOrder)
                    }
                }
                .onAppear() {
                    sort(by: sortOrder)
                }
            }
        }
        .listStyle(.inset)
    }

    // -- here
    private func sort(by sortOrder: SortOrder) {
        switch sortOrder {
        case .alphabetical: animals.sort(by: sortReverse ? { $0.name > $1.name } : { $0.name < $1.name } )
        case .numerical:    animals.sort(by: sortReverse ? { $0.number > $1.number } : { $0.number < $1.number })
        }
    }
    
}

try something like this, with a double tap on the picker buttons:

struct ContentView: View {
    @State private var animals = [
        Animal(name: "Lion", number: 1),
        Animal(name: "Monkey", number: 2),
        Animal(name: "Elephant", number: 3),
    ]
    @State var sortOrder: SortOrder = .alphabetical
    @State var sortReverse = false  // <-- here
    
    var body: some View {
        List {
            Section {
                ForEach(animals) { animal in
                    HStack {
                        Text(animal.name)
                        Spacer()
                        Text("\(animal.number)")
                    }
                }
            } header: {
                VStack(alignment: .leading, spacing: 0) {
                    Text("Sort:")
                    HStack {
                        Picker("Sorting methods", selection: $sortOrder) {
                            ForEach(SortOrder.allCases, id: \.self) { sortOrder in
                                Text(sortOrder.description)
                            }
                        }
                        .onTapGesture(count: 2) { // <-- here
                            sortReverse.toggle()
                            sort(by: sortOrder)
                        }
                        .pickerStyle(.segmented)
                    }
                }
                .onChange(of: sortOrder) { sortOrder in
                    withAnimation {
                        sortReverse = false  // <-- here
                        sort(by: sortOrder)
                    }
                }
                .onAppear() {
                    sort(by: sortOrder)
                }
            }
        }
        .listStyle(.inset)
    }

    // -- here
    private func sort(by sortOrder: SortOrder) {
        switch sortOrder {
        case .alphabetical: animals.sort(by: sortReverse ? { $0.name > $1.name } : { $0.name < $1.name } )
        case .numerical:    animals.sort(by: sortReverse ? { $0.number > $1.number } : { $0.number < $1.number })
        }
    }
    
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文