如何在 Swiftui 导航旁边添加按钮 link
How to add buttons next to a Swiftui navigation link
我正在制作一个简单的清单应用程序,可让您查看有关项目的更多详细信息。我希望能够点击复选框(圆圈按钮)以删除项目或单击导航的其余部分 link 以进入该单独的页面。这是我在导航视图中嵌入列表的代码:
List {
ForEach(fruitIds, id: \.self) { fruitId in
HStack {
Button {
fruitIds.removeLast()
fruits.remove(at: fruitId)
} label: {
Image(systemName: "circle")
.imageScale(.large)
.foregroundColor(.accentColor)
}
NavigationLink(destination: Text(fruits[fruitId])) {
Text(fruits[fruitId])
}
}
}
}
目前,按下按钮或导航 link 会将您转到另一个屏幕,删除项目,然后将您送回列表。
顺便说一句,我声明了这两个数组
@State var fruits: [String] = ["apple", "orange", "banana", "peach"]
@State var fruitIds: [Int] = [0, 1, 2, 3]
此外,我对 Swift 还很陌生,绝对有更好的方法来完成此列表。
我正在从 那里回答你的按钮问题,所以请在此处注明。也可以在 .background()
中使用带有编程触发的 NavigationLink
的 Button
作为 NavigationLink
。让它看起来像股票可能很棘手,这个解决方案可以满足你的要求。这个 不过,你也问了list的问题,这个问题很重要,理解一下。
首先,如果可能的话,避免在 List
、ForEach
等中使用 id: \.self
。原因是它非常脆弱,会回来咬你当您尝试删除或移动项目时,或者列表中有两个“相同”项目时。你真的应该为此使用可识别的结构。对于这个答案,我使用:
struct Fruit: Identifiable {
let id = UUID()
var type: String
// var color: Color, etc.
}
然后视图变成:
struct FruitListView: View {
// This array can have duplicate fruits and the ForEach is unaffected as the id's are different.
@State var fruits: [Fruit] = [Fruit(type: "apple"),
Fruit(type: "orange"),
Fruit(type: "orange"),
Fruit(type: "banana"),
Fruit(type: "banana"),
Fruit(type: "peach")]
var body: some View {
List {
// Since Fruit conforms to Identifiable, you do not need id:
ForEach(fruits) { fruit in
HStack {
Button {
fruits.removeAll(where: { [=11=].id == fruit.id })
} label: {
Image(systemName: "circle")
.imageScale(.large)
.foregroundColor(.accentColor)
}
.buttonStyle(PlainButtonStyle()) // This is necessary to capture the click
.frame(width: 40)
// .contentShape makes a larger tap area to take up the height of the row.
.contentShape(Rectangle())
// You can use fruit directly as it is a Fruit and an element of fruits
NavigationLink(destination: Text(fruit.type)) {
Text(fruit.type)
}
}
}
// This is a standard delete. Try implementing it in your code. You will likely get a crash.
.onDelete(perform: delete)
}
}
func delete(at offsets: IndexSet) {
fruits.remove(atOffsets: offsets)
}
}
我正在制作一个简单的清单应用程序,可让您查看有关项目的更多详细信息。我希望能够点击复选框(圆圈按钮)以删除项目或单击导航的其余部分 link 以进入该单独的页面。这是我在导航视图中嵌入列表的代码:
List {
ForEach(fruitIds, id: \.self) { fruitId in
HStack {
Button {
fruitIds.removeLast()
fruits.remove(at: fruitId)
} label: {
Image(systemName: "circle")
.imageScale(.large)
.foregroundColor(.accentColor)
}
NavigationLink(destination: Text(fruits[fruitId])) {
Text(fruits[fruitId])
}
}
}
}
目前,按下按钮或导航 link 会将您转到另一个屏幕,删除项目,然后将您送回列表。
顺便说一句,我声明了这两个数组
@State var fruits: [String] = ["apple", "orange", "banana", "peach"]
@State var fruitIds: [Int] = [0, 1, 2, 3]
此外,我对 Swift 还很陌生,绝对有更好的方法来完成此列表。
我正在从 .background()
中使用带有编程触发的 NavigationLink
的 Button
作为 NavigationLink
。让它看起来像股票可能很棘手,这个解决方案可以满足你的要求。这个 不过,你也问了list的问题,这个问题很重要,理解一下。
首先,如果可能的话,避免在 List
、ForEach
等中使用 id: \.self
。原因是它非常脆弱,会回来咬你当您尝试删除或移动项目时,或者列表中有两个“相同”项目时。你真的应该为此使用可识别的结构。对于这个答案,我使用:
struct Fruit: Identifiable {
let id = UUID()
var type: String
// var color: Color, etc.
}
然后视图变成:
struct FruitListView: View {
// This array can have duplicate fruits and the ForEach is unaffected as the id's are different.
@State var fruits: [Fruit] = [Fruit(type: "apple"),
Fruit(type: "orange"),
Fruit(type: "orange"),
Fruit(type: "banana"),
Fruit(type: "banana"),
Fruit(type: "peach")]
var body: some View {
List {
// Since Fruit conforms to Identifiable, you do not need id:
ForEach(fruits) { fruit in
HStack {
Button {
fruits.removeAll(where: { [=11=].id == fruit.id })
} label: {
Image(systemName: "circle")
.imageScale(.large)
.foregroundColor(.accentColor)
}
.buttonStyle(PlainButtonStyle()) // This is necessary to capture the click
.frame(width: 40)
// .contentShape makes a larger tap area to take up the height of the row.
.contentShape(Rectangle())
// You can use fruit directly as it is a Fruit and an element of fruits
NavigationLink(destination: Text(fruit.type)) {
Text(fruit.type)
}
}
}
// This is a standard delete. Try implementing it in your code. You will likely get a crash.
.onDelete(perform: delete)
}
}
func delete(at offsets: IndexSet) {
fruits.remove(atOffsets: offsets)
}
}