Reputation: 91
How to set sort order for the below button items (ignore and pin) ? Its not showing in the exact sort order in the menu list. I think os itself is updating the sort order. is there any option to restrict the same?
struct ContentView: View {
var body: some View {
Menu {
Button(action: {
self.self.placeOrder()
}) {
HStack {
Text("Ignore")
.multilineTextAlignment(.leading)
Image("Menu_Ignore")
.renderingMode(.original)
}
}
Button(action: {
self.adjustOrder()
}) {
HStack {
Text("Pin")
.multilineTextAlignment(.leading)
Image("Menu_Pin")
.renderingMode(.original)
}
}
} label: {
Label("Options", systemImage: "paperplane")
}
}
func placeOrder() { }
func adjustOrder() { }}
Upvotes: 8
Views: 3327
Reputation: 6911
As mentioned by Asperi, it's possible in iOS 16 & macOS 13 https://developer.apple.com/documentation/swiftui/text/menuorder(_:)
Your code is totally fine and it works perfectly. The problem you have probably relates to the fact that the first menu item will always appear closest to the View
that the user tapped on to trigger the Menu
. ("Menu
label" in your example).
So if the tapped object is low on the screen, then the system might show the menu above instead of below the tap. When it does this, it reverses the order.
This might be not clear with 2 Menu
items (because if you reverse them it might look as a random change of the order) but if you add more you'll see that the order stays the same but the whole Menu
might be shown either below the tap with the normal order or above the tap with the reversed order.
Upvotes: 3
Reputation: 257711
Now we have environment value to manage this:
var body: some View {
Menu {
// .. buttons here
}
.environment(\.menuOrder, .fixed) // << here !!
}
Upvotes: 20
Reputation: 31
It feels like a force, but I solved it by getting the global y position of Menu with GeometryReader and setting the order at the top or bottom of the screen.
The position where you tapped the Menu (top or bottom) determines the order of the elements in the Menu, so I used that characteristic.
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView {
GeometryReader { geometry in
Menu("show menu") {
// get global position
let frame = geometry.frame(in: .global)
// top or bottom
let isTop = frame.midY <= UIScreen.main.bounds.height/2
if isTop {
Button("first button", action: {})
Button("second button", action: {})
}
else {
Button("second button", action: {})
Button("first button", action: {})
}
}
}
.padding(.vertical, 800)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Upvotes: 3