我的问题很简单,我正在尝试实现类似于Apple TV应用程序上下文菜单的东西:
但就我而言,上下文菜单在 LazyVGrid 外部打开,而不是在网格项旁边打开,并且上下文菜单没有获取所选项目的上下文,但始终获取第一个项目的数据:
我的代码:
struct HomeView: View {
var test : [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12", "Item 13", "Item 14"]
var body: some View {
NavigationStack() {
List{
Section(header: Text("Test")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.primary)) {
ScrollView(.vertical, showsIndicators: false) {
LazyVGrid(columns: [GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())], alignment: .leading, spacing: 80) {
ForEach(test, id: \.self) { item in
Button(item) {
}.buttonStyle(MyButtonStyle()).contextMenu {
Text("Context Menu for : \(item)")
Button("Add Favorite") {}
}
}
}
}
}.contentMargins(30)
}
}
}
}
struct MyButtonStyle: PrimitiveButtonStyle {
@Environment(\.isFocused) var focused: Bool
@State private var isFocused: Bool = false
func makeBody(configuration: Configuration) -> some View {
configuration.label
.compositingGroup()
.frame(minWidth: 250,maxWidth: 250, minHeight: 125, maxHeight: 125)
.padding([.all], 10)
.multilineTextAlignment(.center)
.focusable(true, onFocusChange: { focused in
if focused {
isFocused = true
} else {
isFocused = false
}
})
.background(RoundedRectangle(cornerRadius: 20).fill(isFocused ? .blue : .gray).opacity(0.7))
.foregroundColor(isFocused ? .white : .white)
.onTapGesture(perform: configuration.trigger)
}
}
您可以使用
a
Button
组件,并指定一个“主要操作”,即按下它时要执行的行为,而不是使用
Menu
并尝试向其添加上下文菜单。
Menu {
Button("Favorite") { ... }
Button("Mark as watched") { ... }
} label: {
// This is where your visual content goes
} primaryAction: {
// this code block is executed on single tap
}
这个原生组件应该减少您需要编写的自定义代码量,并且更有可能与
LazyVStack
的布局引擎完美配合。