我如何知道 SwiftUI 按钮是否为 enabled/disabled?
How can I know if a SwiftUI Button is enabled/disabled?
SwiftUI 按钮没有 isEnabled
属性。我怎么知道它是否已启用?
在常规的 UIKit 中,我会简单地做
if button.isEnabeld == true {
} else {
}
但没有等效的 SwiftUI。
SwiftUI 的整体理念是避免重复真实来源。你需要换位思考,考虑真相的来源。这是您需要去了解按钮状态的地方。不是来自按钮本身。
在"Data Flow Through SwiftUI"的第30:50分钟,他们解释说每条数据都有一个单真相的来源。如果您的按钮从某些 @Binding、@State、@EnvironmentObject 等获取其状态,则您的 if 语句也应该从同一位置获取该信息,而不是从按钮获取该信息。
在视图中,如果您希望对 .disabled(true)
设置的状态做出反应,您可以使用:
@Environment(\.isEnabled) var isEnabled
由于环境可以在 View 或 ViewModifier 中使用,因此可用于根据从外部设置的状态更改视图的布局属性。
不幸的是,ButtonStyle
不能直接使用 @Environment
,但您可以使用 ViewModifier
将环境值注入 ButtonStyle
以便使用内部值一个 ButtonStyle
:
// First create a button style that gets the isEnabled value injected
struct MyButtonStyle: ButtonStyle {
private let isEnabled: Bool
init(isEnabled: Bool = true) {
self.isEnabled = isEnabled
}
func makeBody(configuration: Configuration) -> some View {
return configuration
.label
.background(isEnabled ? .green : .gray)
.foregroundColor(isEnabled ? .black : .white)
}
}
// Then make a ViewModifier to inject the state
struct MyButtonModifier: ViewModifier {
@Environment(\.isEnabled) var isEnabled
func body(content: Content) -> some View {
return content.buttonStyle(MyButtonStyle(isEnabled: isEnabled))
}
}
// Then create a convenience function to apply the modifier
extension Button {
func styled() -> some View {
ModifiedContent(content: self, modifier: MyButtonModifier())
}
}
// Finally, try out the button and watch it respond to it's state
struct ContentView: View {
var body: some View {
Button("Test", {}).styled().disabled(true)
}
}
您可以使用此方法将其他内容注入 ButtonStyle,例如尺寸类别和主题。
我将它与自定义样式枚举一起使用,其中包含我们设计系统中发现的所有按钮样式风格。
从视图外部你应该知道你是否使用了 .disabled(true)
修饰符。
从视图内部您可以使用 @Environment(\.isEnabled)
获取该信息:
struct MyButton: View {
let action: () -> Void
@Environment(\.isEnabled) private var isEnabled
var body: some View {
Button(action: action) {
Text("Click")
}
.foregroundColor(isEnabled ? .green : .gray)
}
}
struct MyButton_Previews: PreviewProvider {
static var previews: some View {
VStack {
MyButton(action: {})
MyButton(action: {}).disabled(true)
}
}
}
SwiftUI 按钮没有 isEnabled
属性。我怎么知道它是否已启用?
在常规的 UIKit 中,我会简单地做
if button.isEnabeld == true {
} else {
}
但没有等效的 SwiftUI。
SwiftUI 的整体理念是避免重复真实来源。你需要换位思考,考虑真相的来源。这是您需要去了解按钮状态的地方。不是来自按钮本身。
在"Data Flow Through SwiftUI"的第30:50分钟,他们解释说每条数据都有一个单真相的来源。如果您的按钮从某些 @Binding、@State、@EnvironmentObject 等获取其状态,则您的 if 语句也应该从同一位置获取该信息,而不是从按钮获取该信息。
在视图中,如果您希望对 .disabled(true)
设置的状态做出反应,您可以使用:
@Environment(\.isEnabled) var isEnabled
由于环境可以在 View 或 ViewModifier 中使用,因此可用于根据从外部设置的状态更改视图的布局属性。
不幸的是,ButtonStyle
不能直接使用 @Environment
,但您可以使用 ViewModifier
将环境值注入 ButtonStyle
以便使用内部值一个 ButtonStyle
:
// First create a button style that gets the isEnabled value injected
struct MyButtonStyle: ButtonStyle {
private let isEnabled: Bool
init(isEnabled: Bool = true) {
self.isEnabled = isEnabled
}
func makeBody(configuration: Configuration) -> some View {
return configuration
.label
.background(isEnabled ? .green : .gray)
.foregroundColor(isEnabled ? .black : .white)
}
}
// Then make a ViewModifier to inject the state
struct MyButtonModifier: ViewModifier {
@Environment(\.isEnabled) var isEnabled
func body(content: Content) -> some View {
return content.buttonStyle(MyButtonStyle(isEnabled: isEnabled))
}
}
// Then create a convenience function to apply the modifier
extension Button {
func styled() -> some View {
ModifiedContent(content: self, modifier: MyButtonModifier())
}
}
// Finally, try out the button and watch it respond to it's state
struct ContentView: View {
var body: some View {
Button("Test", {}).styled().disabled(true)
}
}
您可以使用此方法将其他内容注入 ButtonStyle,例如尺寸类别和主题。
我将它与自定义样式枚举一起使用,其中包含我们设计系统中发现的所有按钮样式风格。
从视图外部你应该知道你是否使用了 .disabled(true)
修饰符。
从视图内部您可以使用 @Environment(\.isEnabled)
获取该信息:
struct MyButton: View {
let action: () -> Void
@Environment(\.isEnabled) private var isEnabled
var body: some View {
Button(action: action) {
Text("Click")
}
.foregroundColor(isEnabled ? .green : .gray)
}
}
struct MyButton_Previews: PreviewProvider {
static var previews: some View {
VStack {
MyButton(action: {})
MyButton(action: {}).disabled(true)
}
}
}