SwiftUI 按钮选择
SwiftUI Button selection
我正在尝试掌握 SwiftUI 概念(完成了 Apple 的 SwiftUI 教程),但在经历了 UIKit 十年之后,这对我来说似乎很难。
我需要通过点击它们来切换 HStack 中多个按钮的状态(UIKit 的 isSelected
),并更改它们的字体和文本(在 UIKit 世界中我会使用 attributedText
属性 in if
statement examinig isSelected
属性, all in @IBAction
on TouchUpInside
).
我的第一个想法是在其操作块中获取 "reference" 按钮,但感觉这不是 SwiftUI 方式(甚至不可能)。我找到了使用 Configurator 及其 isPressed 属性 的解决方案(这不是我要搜索的内容),但我需要 Button 的行为实际上像切换一样。 SwiftUI 中是否有任何内置的 isSelected 替换,或者我必须使用 @State 或 @BindableObject 制作我自己的 View 实现,这将封装一些手势识别器(看起来非常丑陋)。提前致谢!
我想出了自定义视图,它是这样封装按钮的:
import SwiftUI
struct SelectableButtonStyle: ButtonStyle {
var isSelected = false
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.frame(width: 60.0, height: 60.0, alignment: .center)
.padding()
.background(Color(#colorLiteral(red: 1, green: 0.8980392157, blue: 0.7058823529, alpha: 1)))
.clipShape(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0))
.overlay(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0).stroke(lineWidth: isSelected ? 2.0 : 0.0).foregroundColor(Color.pink))
.animation(.linear)
}
}
struct StatedButton<Label>: View where Label: View {
private let action: (() -> ())?
private let label: (() -> Label)?
@State var buttonStyle = SelectableButtonStyle()
init(action: (() -> ())? = nil, label: (() -> Label)? = nil) {
self.action = action
self.label = label
}
var body: some View {
Button(action: {
self.buttonStyle.isSelected = !self.buttonStyle.isSelected
self.action?()
print("isSelected now is \(self.buttonStyle.isSelected ? "true" : "false")")
}) {
label?()
}
.buttonStyle(buttonStyle)
}
}
如果这个解决方案不好,请告诉我为什么,我真的很感激。而且我还在为一个非常微不足道的问题而苦苦挣扎:如何将我模型的数组元素映射到按钮(即如何检测到底是哪个按钮被点击了),但我想我必须为此创建另一个问题。
我有一个简单的方法可以做到这一点。
@State var selected = false
func createButton() -> some View {
Button(action: {
self.selected.toggle()
}, label: {
Text("Hello World")
.padding(.all, 5)
.background(selected ? Color.blue : Color.white)
.foregroundColor(selected ? Color.white : Color.blue)
})
.overlay(
RoundedRectangle(cornerRadius: 4)
.stroke(Color.blue, lineWidth: 1)
)
}
您可以创建自定义 ButtonStyle 并根据 isPressed
修改配置的标签
struct CustomButton: View {
var body: some View {
Button {
// action
} label: {
Text("Button")
}
.buttonStyle(CustomStyle())
}
}
struct CustomStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.foregroundColor(.white)
.background(configuration.isPressed ? .green : .black)
}
}
我正在尝试掌握 SwiftUI 概念(完成了 Apple 的 SwiftUI 教程),但在经历了 UIKit 十年之后,这对我来说似乎很难。
我需要通过点击它们来切换 HStack 中多个按钮的状态(UIKit 的 isSelected
),并更改它们的字体和文本(在 UIKit 世界中我会使用 attributedText
属性 in if
statement examinig isSelected
属性, all in @IBAction
on TouchUpInside
).
我的第一个想法是在其操作块中获取 "reference" 按钮,但感觉这不是 SwiftUI 方式(甚至不可能)。我找到了使用 Configurator 及其 isPressed 属性 的解决方案(这不是我要搜索的内容),但我需要 Button 的行为实际上像切换一样。 SwiftUI 中是否有任何内置的 isSelected 替换,或者我必须使用 @State 或 @BindableObject 制作我自己的 View 实现,这将封装一些手势识别器(看起来非常丑陋)。提前致谢!
我想出了自定义视图,它是这样封装按钮的:
import SwiftUI
struct SelectableButtonStyle: ButtonStyle {
var isSelected = false
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.frame(width: 60.0, height: 60.0, alignment: .center)
.padding()
.background(Color(#colorLiteral(red: 1, green: 0.8980392157, blue: 0.7058823529, alpha: 1)))
.clipShape(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0))
.overlay(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0).stroke(lineWidth: isSelected ? 2.0 : 0.0).foregroundColor(Color.pink))
.animation(.linear)
}
}
struct StatedButton<Label>: View where Label: View {
private let action: (() -> ())?
private let label: (() -> Label)?
@State var buttonStyle = SelectableButtonStyle()
init(action: (() -> ())? = nil, label: (() -> Label)? = nil) {
self.action = action
self.label = label
}
var body: some View {
Button(action: {
self.buttonStyle.isSelected = !self.buttonStyle.isSelected
self.action?()
print("isSelected now is \(self.buttonStyle.isSelected ? "true" : "false")")
}) {
label?()
}
.buttonStyle(buttonStyle)
}
}
如果这个解决方案不好,请告诉我为什么,我真的很感激。而且我还在为一个非常微不足道的问题而苦苦挣扎:如何将我模型的数组元素映射到按钮(即如何检测到底是哪个按钮被点击了),但我想我必须为此创建另一个问题。
我有一个简单的方法可以做到这一点。
@State var selected = false
func createButton() -> some View {
Button(action: {
self.selected.toggle()
}, label: {
Text("Hello World")
.padding(.all, 5)
.background(selected ? Color.blue : Color.white)
.foregroundColor(selected ? Color.white : Color.blue)
})
.overlay(
RoundedRectangle(cornerRadius: 4)
.stroke(Color.blue, lineWidth: 1)
)
}
您可以创建自定义 ButtonStyle 并根据 isPressed
struct CustomButton: View {
var body: some View {
Button {
// action
} label: {
Text("Button")
}
.buttonStyle(CustomStyle())
}
}
struct CustomStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.foregroundColor(.white)
.background(configuration.isPressed ? .green : .black)
}
}