我想要的
我在做一个组件。此组件用于显示标记列表。我想一个上下文菜单上弹出的标签时,用户长按它。就像这样:
的数据
我得到了什么
的
您可以看到,上下文菜单显示在标记的容器上,而不是标记上。
我的代码
import SwiftUI
import CoreData
struct AddVision: View {
@State private var visionTitle: String = ""
var body: some View {
GeometryReader { geometry in
NavigationView {
Form {
Section(header: Text("Basic Information")) {
TextField("Input Vision Title Please", text: $visionTitle)
}
Section(header: Text("Tags")) {
TagsView(screenWidth: geometry.size.width)
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
addNewVision()
} label: {
Text("Add")
}
}
}
}
}
}
private func addNewVision() {
print("add new vision")
}
}
struct TagsView: View {
@Environment(\.managedObjectContext) private var viewContext
// 标签行数组,每一个元素表示一行标签
@State private var groupedItems: [[Tag]] = [[Tag]]()
// 新标签标题
@State private var newTagTitle = ""
// 显示标签添加输入框
@State private var showNewTagInputField = false
// 显示菜单
@State private var showContextMenu = false
// 显示警告
@State private var showingAlert = false
// 聚焦
@FocusState private var keyboardFocused: Bool
// 屏幕宽度
let screenWidth: CGFloat
init(screenWidth: CGFloat) {
self.screenWidth = screenWidth
}
var body: some View {
VStack(alignment: .leading) {
ForEach(groupedItems, id: \.self) { itms in
HStack {
ForEach(itms, id: \.self) { tag in
Text(tag.title ?? "")
.font(.callout)
.foregroundColor(/*@START_MENU_TOKEN@*/Color(hue: 0.364, saturation: 0.939, brightness: 0.628)/*@END_MENU_TOKEN@*/)
.padding()
.frame(height: /*@START_MENU_TOKEN@*/24.0/*@END_MENU_TOKEN@*/)
.background(Color(hue: 0.387, saturation: 0.969, brightness: 0.965, opacity: 0.207))
.frame(alignment: .center)
.cornerRadius(100)
.contextMenu {
Button {
deleteTheTag(tag)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
}
HStack {
if showNewTagInputField {
TextField("my tag", text: $newTagTitle, onCommit: addTag)
.font(.callout)
.foregroundColor(/*@START_MENU_TOKEN@*/Color(hue: 0.364, saturation: 0.939, brightness: 0.628)/*@END_MENU_TOKEN@*/)
.padding()
.frame(height: /*@START_MENU_TOKEN@*/24.0/*@END_MENU_TOKEN@*/)
.background(Color(hue: 0.387, saturation: 0.969, brightness: 0.965, opacity: 0.207))
.frame(alignment: .center)
.cornerRadius(100)
.focused($keyboardFocused)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
keyboardFocused = true
}
}
}
Button {
showNewTagInputField = true
} label: {
Image(systemName: "plus")
}
.foregroundColor(.white)
.padding()
.background(Color(hue: 1.0, saturation: 0.035, brightness: 0.053, opacity: 0.243))
.frame(height: /*@START_MENU_TOKEN@*/24.0/*@END_MENU_TOKEN@*/)
.frame(alignment: .center)
.cornerRadius(100)
}
.animation(.easeOut, value: showNewTagInputField)
}
.onAppear {
buildTagGroupList()
}
}
private func deleteTheTag(_ tag: Tag) {
// 删除标签
viewContext.delete(tag)
// 刷新标签列表
buildTagGroupList()
}
private func buildTagGroupList() {
// 待处理的标签
var tags = [Tag]()
// 查询标签
let fetchRequest = NSFetchRequest<Tag>(entityName: "Tag")
fetchRequest.sortDescriptors = []
do {
let results = try viewContext.fetch(fetchRequest)
for result in results {
tags.append(result)
}
} catch {
print("查询标签的时候出现错误")
}
var groupedItems: [[Tag]] = [[Tag]]()
// 一行tag已经占据的宽度
var width: CGFloat = 0
// 临时存储一行的元素
var tempItems = [Tag]()
// 循环取出的标签
for word in tags {
// 新建一个Label组件
let label = UILabel()
// 设置Label的内容
label.text = word.title
// 设置label根据里面text的长度改变其宽度
label.sizeToFit()
// label的宽度,一个label两边都16点的padding,所以一个label的宽度需要加上32
let labelWidth = label.frame.size.width + 32
if (width + labelWidth + 32) < screenWidth {
width += labelWidth
tempItems.append(word)
} else {
width = labelWidth
groupedItems.append(tempItems)
tempItems.removeAll()
tempItems.append(word)
}
}
groupedItems.append(tempItems)
self.groupedItems = groupedItems
}
private func addTag() {
// 检查是否输入内容
if self.newTagTitle.isEmpty {
// 关闭新标签添加输入框
showNewTagInputField = false
return
}
// 向数据库中添加一个标签
let tag = Tag(context: viewContext)
tag.id = UUID()
tag.title = self.newTagTitle
do {
try viewContext.save()
} catch {
print("保存新标签的时候出现错误")
}
// 重新获取数据
buildTagGroupList()
// 清空新标签输入框
self.newTagTitle.removeAll()
// 关闭新标签添加输入框
showNewTagInputField = false
}
}
struct AddVision_Previews: PreviewProvider {
static var previews: some View {
AddVision()
.environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
字符串
我试过几种方法,但都失败了。
我应该如何修改我的代码?
谢啦,谢啦
我用谷歌搜索这个问题,关键词是这样的:
SwiftUI contextMenu不应用于子视图,而是应用于父视图
不幸的是,我没有找到我需要的东西。
我也尝试了Youbube与关键词,但我得到的T_T较少
我问GPT几次,它确实给了我一些解决方案,我尝试了所有的
全部失败T_T
1条答案
按热度按时间pvcm50d11#
下面的代码对我来说工作正常(Xcode 15 beta 5)。如果问题仍然存在,您应该编辑您的问题并添加编译所需的所有代码(How to create a Minimal, Reproducible Example)。
字符串
的数据