我有一个按钮。我想为突出显示状态设置自定义背景颜色。如何在SwiftUI中做到这一点?
Button(action: signIn) {
Text("Sign In")
}
.padding(.all)
.background(Color.red)
.cornerRadius(16)
.foregroundColor(.white)
.font(Font.body.bold())
答案 0 :(得分:4)
我一直在寻找类似的功能,所以我通过以下方式做到了。
我创建了一个特殊的View结构,以所需的样式返回一个Button,在此结构中,我添加了一个State属性。我有一个名为'table'的变量,它是一个Int变量,因为我的按钮是带有数字的圆形按钮
struct TableButton: View {
@State private var selected = false
var table: Int
var body: some View {
Button("\(table)") {
self.selected.toggle()
}
.frame(width: 50, height: 50)
.background(selected ? Color.blue : Color.red)
.foregroundColor(.white)
.clipShape(Circle())
}
}
然后我在内容中使用查看代码
HStack(spacing: 10) {
ForEach((1...6), id: \.self) { table in
TableButton(table: table)
}
}
这将创建一个带有6个按钮的水平堆栈,这些按钮在选中时为蓝色,在取消选中时为红色。
我不是一个经验丰富的开发人员,只是尝试了所有可能的方法,直到发现它对我有用,希望它对其他人也有用。
答案 1 :(得分:3)
据我所知,目前尚无官方支持的方法。您可以使用以下解决方法。这样产生的行为与UIKit中的行为相同,在UIKit中,点击按钮并将手指从其上拖动将使该按钮保持突出状态。
struct HoverButton<Label>: View where Label: View {
private let action: () -> ()
private let label: () -> Label
init(action: @escaping () -> (), label: @escaping () -> Label) {
self.action = action
self.label = label
}
@State private var pressed: Bool = false
var body: some View {
Button(action: action) {
label()
.foregroundColor(pressed ? .red : .blue)
.gesture(DragGesture(minimumDistance: 0.0)
.onChanged { _ in self.pressed = true }
.onEnded { _ in self.pressed = false })
}
}
}
答案 2 :(得分:2)
SwiftUI实际上为此expose an API:ButtonStyle
。
struct MyButtonStyle : ButtonStyle {
func body(configuration: Button<Self.Label>, isPressed: Bool) -> some View {
configuration
.overlay(configuration) // Works around SwiftUI automatically changing opacity.
.padding()
.foregroundColor(.white)
.background(isPressed ? Color.red : Color.blue)
.cornerRadius(8.0)
}
}
extension StaticMember where Base: ButtonStyle {
static var myStyle: StaticMember<MyButtonStyle> {
return .init(MyButtonStyle())
}
}
// to use it
Button(action: {}) {
Text("Hello World")
}
.buttonStyle(.myStyle)
正如我在.overlay(...)
之后的注释中所指出的那样,当前(测试版3)SwiftUI始终会自动更改按钮内容的不透明度。我已经对此提出了反馈,因为使用自定义按钮样式似乎应该完全覆盖这种行为。对我来说似乎是个虫子。
答案 3 :(得分:1)
这适用于对上述解决方案不满意的人,因为他们提出了其他问题,例如手势重叠(例如,现在很难在滚动视图中使用此解决方案)。另一个关键是创建这样的自定义按钮样式
struct CustomButtonStyle<Content>: ButtonStyle where Content: View {
var change: (Bool) -> Content
func makeBody(configuration: Self.Configuration) -> some View {
return change(configuration.isPressed)
}
}
因此,我们应该只传递闭包,闭包将返回按钮的状态并基于此参数创建按钮。它将像这样使用:
struct CustomButton<Content>: View where Content: View {
var content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
Button(action: { }, label: {
EmptyView()
})
.buttonStyle(CustomButtonStyle(change: { bool in
Text("\(bool ? "yo" : "yo2")")
}))
}
}
答案 4 :(得分:0)
好吧,让我再次清除一切。这是确切的解决方案
struct StateableButton<Content>: ButtonStyle where Content: View {
var change: (Bool) -> Content
func makeBody(configuration: Configuration) -> some View {
return change(configuration.isPressed)
}
}
Button(action: {
print("Do something")
}, label: {
// Don't create your button view in here
EmptyView()
})
.buttonStyle(StateableButton(change: { state in
// Create your button view in here
return HStack {
Image(systemName: "clock.arrow.circlepath")
Text(item)
Spacer()
Image(systemName: "arrow.up.backward")
}
.padding(.horizontal)
.frame(height: 50)
.background(state ? Color.black : Color.clear)
}))