Reputation: 36088
I'm displaying sort options in my Menu
, but I'd also like the user to control the sort direction in the way the Files app works: tapping a second time toggles the sort direction.
Here's what I have:
@State private var selectedSort: SortOption = .name
@State private var isSortAscending = true
enum SortOption {
case name
case number
case length
}
Menu {
Picker(selection: $selectedSort, label: Text("Sorting options")) {
Button {
isSortAscending.toggle()
} label: {
HStack {
Text("Name")
Spacer()
Image(systemName: isSortAscending ? "chevron.down" : "chevron.up")
}
}
.tag(SortOption.name)
Button {
isSortAscending.toggle()
} label: {
HStack {
Text("Number")
Spacer()
Image(systemName: isSortAscending ? "chevron.down" : "chevron.up")
}
}
.tag(SortOption.number)
Button {
isSortAscending.toggle()
} label: {
HStack {
Text("Length")
Spacer()
Image(systemName: isSortAscending ? "chevron.down" : "chevron.up")
}
}
.tag(SortOption.length)
}
}
Tapping doesn't toggle the sort state at all. Is there a better or more supported way to do this?
Upvotes: 1
Views: 375
Reputation: 257711
Item selected is handled internally, so we need selection side-effect. It is possible to do by injecting will-set
side effect in computable binding.
Here is a possible approach tested with Xcode 13.4 / iOS 15.5
Main part:
var sorting: Binding<SortOption> { .init(
get: { self.selectedSort },
set: {
if self.selectedSort == $0 {
self.isSortAscending.toggle()
}
self.selectedSort = $0
}
)}
var body: some View {
Menu("Sort") {
Picker(selection: sorting, label: Text("Sorting options")) {
ForEach(SortOption.allCases) { option in
HStack {
Text(option.rawValue)
Spacer()
if selectedSort == option {
Image(systemName: isSortAscending ? "chevron.down" : "chevron.up")
}
Upvotes: 3