列表行中的多个按钮

假设我有一个 List和两个按钮在一行,我如何能够区分哪个按钮被点击没有整个行高亮?

对于此示例代码,当单击行中的任何一个按钮时,都会调用这两个按钮的操作回调。

// a simple list with just one row
List {


// both buttons in a HStack so that they appear in a single row
HStack {
Button {
print("button 1 tapped")
} label: {
Text("One")
}
            

Button {
print("button 2 tapped")
} label: {
Text("Two")
}
}
}

当只有一个按钮被点击一次时,我看到两个按钮的回调都被调用,这不是我想要的:

button 1 tapped
button 2 tapped
24312 次浏览

Seems to be a specific issue concerning Button when contained in a List row.

Workaround:

List {
HStack {
Text("One").onTapGesture { print("One") }
Text("Two").onTapGesture { print("Two") }
}
}

This yields the desired output.

You can also use a Group instead of Text to have a sophisticated design for the "buttons".

One of the differences with SwiftUI is that you are not creating specific instances of, for example UIButton, because you might be in a Mac app. With SwiftUI, you are requesting a button type thing.

In this case since you are in a list row, the system gives you a full size, tap anywhere to trigger the action, button. And since you've added two of them, both are triggered when you tap anywhere.

You can add two separate Views and give them a .onTapGesture to have them act essentially as buttons, but you would lose the tap flash of the cell row and any other automatic button like features SwiftUI would give.

List {
HStack {
Text("One").onTapGesture {
print("Button 1 tapped")
}


Spacer()


Text("Two").onTapGesture {
print("Button 2 tapped")
}
}
}

You need to create your own ButtonStyle:

  struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(.accentColor)
.opacity(configuration.isPressed ? 0.5 : 1.0)
}
}


struct IdentifiableString: Identifiable {
let text: String
var id: String { text }
}


struct Test: View {
var body: some View {
List([
IdentifiableString(text: "Line 1"),
IdentifiableString(text: "Line 2"),
]) {
item in
HStack {
Text("\(item.text)")
Spacer()
Button(action: { print("\(item.text) 1")}) {
Text("Button 1")
}
Button(action: { print("\(item.text) 2")}) {
Text("Button 2")
}
}
}.buttonStyle(MyButtonStyle())
}
}

You need to use BorderlessButtonStyle() or PlainButtonStyle().

    List([1, 2, 3], id: \.self) { row in
HStack {
Button(action: { print("Button at \(row)") }) {
Text("Row: \(row) Name: A")
}
.buttonStyle(BorderlessButtonStyle())
            

Button(action: { print("Button at \(row)") }) {
Text("Row: \(row) Name: B")
}
.buttonStyle(PlainButtonStyle())
}
}