我如何知道 SwiftUI 按钮是不是已启用/禁用?

Posted

技术标签:

【中文标题】我如何知道 SwiftUI 按钮是不是已启用/禁用?【英文标题】:How can I know if a SwiftUI Button is enabled/disabled?我如何知道 SwiftUI 按钮是否已启用/禁用? 【发布时间】:2019-07-02 09:14:32 【问题描述】:

SwiftUI 按钮没有isEnabled 属性。如何判断它是否已启用?

在常规的 UIKit 中,我会这样做

if button.isEnabeld == true 
 else 

但没有 SwiftUI 等价物。

【问题讨论】:

你在使用任何库吗?分享详情代码。 我正在使用 Apple Xcode 11 Beta 发布的 SwiftUI(无外部库)。有一个按钮。我想知道如何判断它是否启用/禁用。没有要添加的代码。问题就这么简单。 @MartinR 如果我要自己设置按钮的状态,我可以使用它。但在这种情况下,按钮的状态已经在我的代码中的其他位置设置。该按钮现在传递给 functionX。现在在functionX里面,我想知道按钮的状态是什么? @iosCalendarpatchthecode.com 按钮状态是从您的应用程序状态生成的。检查应用状态,不检查 UI 状态。 我不知道更好的表达方式,但如果您不考虑“推”而不是“拉”,那只会更复杂。听起来您正在与SwiftUI 的基本概念作斗争。正如@sulthan 所说,为什么要向 UI 查询应用所拥有的东西? 【参考方案1】:

在视图中,如果您希望对.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,例如尺寸类别和主题。

我将它与自定义样式枚举一起使用,该枚举包含我们设计系统中的所有按钮样式风格。

【讨论】:

不错的答案,您可以通过创建将configuration 作为输入的MyButton 来简化解决方案。在MyButtonStyle.makeBody 中返回MyButton(configuration: configuration)。在按钮内,您可以使用 Environment 检查它是否已启用。所以MyButton 具有所有逻辑,MyButtonStyle 只是一个包装器 嗨@user1046037 你介意把它写成代码吗? 没关系找到答案。谢谢! ***.com/a/59210692/15585355【参考方案2】:

如果您使用了.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)
        
    

【讨论】:

【参考方案3】:

SwiftUI 的整体理念是避免重复数据源。你需要换个角度思考,想想真相的来源在哪里。这是您需要了解按钮状态的地方。不是来自按钮本身。

在“通过 SwiftUI 的数据流”中,在 30:50 分钟,他们解释说每条数据都有一个单一事实来源。如果您的按钮从某个 @Binding、@State、@EnvironmentObject 等获取其状态,那么您的 if 语句也应该从同一个位置获取该信息,而不是从按钮。

【讨论】:

基于上面的cmets,我认为你是正确的。谢谢,我会重新考虑我的逻辑 不客气。如果您还没有,那么 WWDC 会话 Data Flow Through SwiftUI 的 37 分钟时间是值得的。您可能会节省很多时间。强烈推荐!干杯。 老实说,这适用于所有类型的 UI,包括 Cocoa/CocoaTouch。这并不是真正的不同类型的思维,而是明确的区别。 @Sulthan 你完全正确,不同的是 SwiftUI 强制执行它,因为它不会使禁用状态可用。 那苹果提供的PlainButtonStyle是怎么知道按钮状态的呢?

以上是关于我如何知道 SwiftUI 按钮是不是已启用/禁用?的主要内容,如果未能解决你的问题,请参考以下文章

你如何在swiftUI中禁用navigationBaritems

通过输入条件禁用/启用按钮 [AngularJS]

使用 SwiftUI 为启用/禁用按钮设置颜色的最智能方法

禁用或启用复选框已选中事件的提交按钮

在 SwiftUi 中禁用默认按钮单击动画

如何启用禁用的按钮