SwiftUI - 列表行中的多个按钮
SwiftUI - Multiple Buttons in a List row
假设我在一行中有一个 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
当包含在 List
行中时,似乎是关于 Button
的特定问题。
解决方法:
List {
HStack {
Text("One").onTapGesture { print("One") }
Text("Two").onTapGesture { print("Two") }
}
}
这会产生所需的输出。
您也可以使用 Group
而不是 Text
来对 "buttons" 进行复杂的设计。
与 SwiftUI 的区别之一是您不会创建特定实例,例如 UIButton,因为您可能在 Mac 应用程序中。使用 SwiftUI,您正在请求一个按钮类型的东西。
在这种情况下,由于您在列表行中,系统会为您提供全尺寸,点击任意位置以触发操作,按钮。由于您已经添加了其中两个,因此当您点击任意位置时都会触发它们。
您可以添加两个单独的视图并给它们一个 .onTapGesture
让它们本质上充当按钮,但是您将失去单元格行的点击闪光和任何其他自动按钮,如 SwiftUI 提供的功能。
List {
HStack {
Text("One").onTapGesture {
print("Button 1 tapped")
}
Spacer()
Text("Two").onTapGesture {
print("Button 2 tapped")
}
}
}
您需要创建自己的 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())
}
}
您需要使用 BorderlessButtonStyle() 或 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())
}
}
假设我在一行中有一个 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
当包含在 List
行中时,似乎是关于 Button
的特定问题。
解决方法:
List {
HStack {
Text("One").onTapGesture { print("One") }
Text("Two").onTapGesture { print("Two") }
}
}
这会产生所需的输出。
您也可以使用 Group
而不是 Text
来对 "buttons" 进行复杂的设计。
与 SwiftUI 的区别之一是您不会创建特定实例,例如 UIButton,因为您可能在 Mac 应用程序中。使用 SwiftUI,您正在请求一个按钮类型的东西。
在这种情况下,由于您在列表行中,系统会为您提供全尺寸,点击任意位置以触发操作,按钮。由于您已经添加了其中两个,因此当您点击任意位置时都会触发它们。
您可以添加两个单独的视图并给它们一个 .onTapGesture
让它们本质上充当按钮,但是您将失去单元格行的点击闪光和任何其他自动按钮,如 SwiftUI 提供的功能。
List {
HStack {
Text("One").onTapGesture {
print("Button 1 tapped")
}
Spacer()
Text("Two").onTapGesture {
print("Button 2 tapped")
}
}
}
您需要创建自己的 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())
}
}
您需要使用 BorderlessButtonStyle() 或 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())
}
}