如何有条件地呈现SwiftUI上下文菜单?
考虑以下视图代码:如何有条件地呈现SwiftUI上下文菜单?,swiftui,viewmodifier,Swiftui,Viewmodifier,考虑以下视图代码: Text("Something") .contextMenu { // Some menu options } 这个很好用。我想做的是:通过视图修改器间接显示contextMenu。大概是这样的: Text("Something") .modifier(myContextMenu) { // Some menu options } 为什么:我需要在修饰符中做一些逻辑来有条件地显示或不显示菜单。我无法为它计算出正确的视图修改器签名 还有另一个contextM
Text("Something")
.contextMenu {
// Some menu options
}
这个很好用。我想做的是:通过视图修改器间接显示contextMenu。大概是这样的:
Text("Something")
.modifier(myContextMenu) {
// Some menu options
}
为什么:我需要在修饰符中做一些逻辑来有条件地显示或不显示菜单。我无法为它计算出正确的视图修改器签名
还有另一个contextMenu修饰符,它声称我可以有条件地为它呈现上下文菜单。在尝试这一点时,这对我没有帮助,因为只要我将contextMenu修改器添加到iOS上的NavigationLink,它上的点击手势就会停止工作。下面的回复中有讨论
如何使用视图修改器显示关联菜单?类似的内容
Text("Options")
.contextMenu {
if (1 == 0) { // some if statements here
Button(action: {
//
}) {
Text("Choose Country")
Image(systemName: "globe")
}
}
}
像这样的
Text("Options")
.contextMenu {
if (1 == 0) { // some if statements here
Button(action: {
//
}) {
Text("Choose Country")
Image(systemName: "globe")
}
}
}
下面是一个使用Xcode 11.2/iOS 13.2测试的可选上下文菜单用法的演示
struct TestConditionalContextMenu: View {
@State private var hasContextMenu = false
var body: some View {
VStack {
Button(hasContextMenu ? "Disable Menu" : "Enable Menu")
{ self.hasContextMenu.toggle() }
Divider()
Text("Hello, World!")
.background(Color.yellow)
.contextMenu(self.hasContextMenu ?
ContextMenu {
Button("Do something1") {}
Button("Do something2") {}
} : nil)
}
}
}
下面是一个使用Xcode 11.2/iOS 13.2测试的可选上下文菜单用法的演示
struct TestConditionalContextMenu: View {
@State private var hasContextMenu = false
var body: some View {
VStack {
Button(hasContextMenu ? "Disable Menu" : "Enable Menu")
{ self.hasContextMenu.toggle() }
Divider()
Text("Hello, World!")
.background(Color.yellow)
.contextMenu(self.hasContextMenu ?
ContextMenu {
Button("Do something1") {}
Button("Do something2") {}
} : nil)
}
}
}
这是我想到的。不完全满意,它可以更紧凑,但它的工作如预期
struct ListView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: ItemView(item: "Something")) {
Text("Something").modifier(withiOSContextMenu())
}.modifier(withOSXContextMenu())
}
}
}
}
struct withOSXContextMenu: ViewModifier {
func body(content: Content) -> some View {
#if os(OSX)
return content.contextMenu(ContextMenu {
ContextMenuContent()
})
#else
return content
#endif
}
}
struct withiOSContextMenu: ViewModifier {
func body(content: Content) -> some View {
#if os(iOS)
return content.contextMenu(ContextMenu {
ContextMenuContent()
})
#else
return content
#endif
}
}
func ContextMenuContent() -> some View {
Group {
Button("Click me") {
print("Button clicked")
}
Button("Another button") {
print("Another button clicked")
}
}
}
这是我想到的。不完全满意,它可以更紧凑,但它的工作如预期
struct ListView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: ItemView(item: "Something")) {
Text("Something").modifier(withiOSContextMenu())
}.modifier(withOSXContextMenu())
}
}
}
}
struct withOSXContextMenu: ViewModifier {
func body(content: Content) -> some View {
#if os(OSX)
return content.contextMenu(ContextMenu {
ContextMenuContent()
})
#else
return content
#endif
}
}
struct withiOSContextMenu: ViewModifier {
func body(content: Content) -> some View {
#if os(iOS)
return content.contextMenu(ContextMenu {
ContextMenuContent()
})
#else
return content
#endif
}
}
func ContextMenuContent() -> some View {
Group {
Button("Click me") {
print("Button clicked")
}
Button("Another button") {
print("Another button clicked")
}
}
}
该死。我希望我能接受这个答案。这看起来是正确的,而且有效,但事实证明,我的情况更复杂。我这样做的唯一原因是,在iOS和OSX中为不同的项目附加一个contextMenu。如果连接到NavigationLink,它可以在OSX上工作,但会阻止iOS中的点击。如果附加到NavigationLink中的元素,它在iOS中工作,但在OSX中不显示。我原以为条件附加就是答案,但没有-当我将一个nil contextmenu附加到NavigationLink时,它仍然会阻止点击。谢谢@Asperi回答每一个SwiftUI问题。该死。我希望我能接受这个答案。这看起来是正确的,而且有效,但事实证明,我的情况更复杂。我这样做的唯一原因是,在iOS和OSX中为不同的项目附加一个contextMenu。如果连接到NavigationLink,它可以在OSX上工作,但会阻止iOS中的点击。如果附加到NavigationLink中的元素,它在iOS中工作,但在OSX中不显示。我认为条件附加是答案,但不是-当我将nil contextmenu附加到NavigationLink时,它仍然会阻止点击。感谢@Asperi回答每一个SwiftUI问题。