根据我的理解,要在SwiftUI中设置按钮的样式,请扩展ButtonStyle
并实现func makeBody(configuration: Self.Configuration) -> some View
,在其中开始对configuration.label
进行修改,该修改是对{{ 1}}视图。
现在,除了Button
字段之外,label
还有一个ButtonStyle.Configuration
的布尔字段,但这似乎就是全部。
如何检查按钮是启用还是禁用?
例如,我想在按钮周围绘制边框,如果按钮启用,我希望边框为蓝色,如果按钮禁用,我希望边框为灰色。
我的第一个猜测是这样的:
isPressed
但是没有 func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.overlay(
RoundedRectangle(cornerRadius: 4).stroke(configuration.isEnabled ? Color.blue : Color.gray, lineWidth: 1).padding(8)
)
}
字段。
Apple提供的isEnabled
显然可以访问此信息,因为声明它的头文件中的doc注释说:“样式可以应用视觉效果来指示按下,聚焦或启用的状态。按钮。”
PlainButtonStyle
是否可以访问此信息?
在您建议关闭此问题之前,请先阅读以下内容:
前段时间有一个类似的问题。该问题未指定任何上下文。
在这里,我有一个特定的上下文:创建通用的可重用按钮样式。
那里提供的答案是不够的。我不能指望人们将禁用状态传递给样式构造函数。这太过重复了。
您能想象人们是否必须以这种方式编写代码吗?
/// A `Button` style that does not style or decorate its content while idle.
///
/// The style may apply a visual effect to indicate the pressed, focused,
/// or enabled state of the button.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct PlainButtonStyle : PrimitiveButtonStyle {
.....
显然这是不可取的。
显然,苹果提供的样式可以访问信息,而无需人们再次将禁用状态传递给样式。
如果您关闭问题,将永远阻止任何人在StackOverflow上对该问题提供有用的答案。
在建议关闭之前,请重新考虑。
我猜测,如果您可以获取Button() { .... }.disabled(someExprssion).buttonStyle(MyCustomStyle(disabled: someExpression))
视图的EnvironmentValues.isEnabled
,那么它可能是正确的值。
另一个提出问题的方法是:在SwiftUI中是否有可能获得您未定义自己的视图的环境?
答案 0 :(得分:5)
对@hasen 的回答进行了一些调整,以使事情更易于配置
struct MyButtonStyle: ButtonStyle {
var foreground = Color.white
var background = Color.blue
func makeBody(configuration: ButtonStyle.Configuration) -> some View {
MyButton(foreground: foreground, background: background, configuration: configuration)
}
struct MyButton: View {
var foreground:Color
var background:Color
let configuration: ButtonStyle.Configuration
@Environment(\.isEnabled) private var isEnabled: Bool
var body: some View {
configuration.label
.padding(EdgeInsets(top: 7.0, leading: 7.0, bottom: 7.0, trailing: 7.0))
.frame(maxWidth: .infinity)
.foregroundColor(isEnabled ? foreground : foreground.opacity(0.5))
.background(isEnabled ? background : background.opacity(0.5))
.opacity(configuration.isPressed ? 0.8 : 1.0)
}
}
}
用法
Button(action: {}) {
Text("Hello")
}.buttonStyle(MyButtonStyle(foreground: .white, background: .green))
答案 1 :(得分:1)
您可以将禁用状态合并到buttonStyle中,这样您就不会在应用程序中使用它两次。
struct CustomizedButtonStyle : PrimitiveButtonStyle {
var disabled: Bool = false
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label.disabled(disabled)
.overlay(
RoundedRectangle(cornerRadius: 4).stroke(disabled ? Color.blue : Color.gray, lineWidth: 1).padding(8)
)
}
}
struct ButtonUpdate: View {
var body: some View {
VStack{
Button(action: {
}) { Text("button")
}.buttonStyle(CustomizedButtonStyle(disabled: true))
Button(action: {
}) { Text("button")
}.buttonStyle(CustomizedButtonStyle())
}}
}
答案 2 :(得分:1)
我通过以下博客找到了答案:https://swiftui-lab.com/custom-styling/
您可以通过创建包装器视图并在样式struct中使用它来从环境中获取启用状态:
struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: ButtonStyle.Configuration) -> some View {
MyButton(configuration: configuration)
}
struct MyButton: View {
let configuration: ButtonStyle.Configuration
@Environment(\.isEnabled) private var isEnabled: Bool
var body: some View {
configuration.label.foregroundColor(isEnabled ? Color.green : Color.red)
}
}
}
此示例演示如何获取状态并使用其更改按钮的外观。如果按钮被禁用,它将按钮文本颜色更改为红色,如果启用则将其更改为绿色。
答案 3 :(得分:0)
另一种选择是将disabled
布尔值传递给ButtonStyle
,然后在标签上使用allowsHitTesting
修饰符以有效地禁用按钮:
struct MyButtonStyle: ButtonStyle {
let disabled: Bool
func makeBody(configuration: Self.Configuration) -> some View {
configuration
.label
.allowsHitTesting(!disabled)
}
}