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

lfapxunr  于 2022-10-04  发布在  Swift
关注(0)|答案(5)|浏览(242)

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

在普通的UIKit中,我会简单地做

if button.isEnabeld == true {
} else {
}

但没有类似的SwiftUI。

dluptydi

dluptydi1#

在视图中,如果希望对.disabled(true)设置的状态做出React,可以使用:@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中注入其他内容,如大小、类别和主题。

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

myss37ts

myss37ts2#

从视图外部,您应该知道是否使用了.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)
        }
    }
}
i7uaboj4

i7uaboj43#

SwiftUI的整个理念,是为了避免重复真相的来源。你需要以不同的方式思考,并思考真理的来源在哪里。这是您需要查看按钮状态的地方。而不是从按钮本身。

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

62o28rlo

62o28rlo4#

简而言之:只需在结构中使用:

@Environment(.isEnabled) private var isEnabled

按钮样式:

  • 悬停更改时的动画
  • 关于禁用/启用更改的动画
  • 可在任何按钮上以原生的wiftUI方式应用
  • 需要手动设置按钮外的按钮大小

用法:

@State var isDisabled = false

///.......

Button("Styled button") { isDisabled.toggle() }
    .buttonStyle(ButtStyle.BigButton()) // magic inside
    .frame(width: 200, height: 50)
    .disabled(isDisabled)

Button("switch isDisabled") { isDisabled.toggle() }

源代码:

public struct ButtStyle { }

// Added style to easy stylyng in native way for SwiftUI
@available(macOS 11.0, *)
public extension ButtStyle {
    struct BigButton: ButtonStyle {
        init() {

        }

        public func makeBody(configuration: Configuration) -> some View {
            BigButtonStyleView(configuration: configuration)
        }
    }
}

@available(macOS 11.0, *)
struct BigButtonStyleView : View {
    let configuration: ButtonStyle.Configuration
    @Environment(.isEnabled) var isEnabled // here we getting "disabled"

    @State var hover : Bool = false

    var body: some View {
        // added animations
        MainFrameMod()
            .animation(.easeInOut(duration: 0.2), value: hover)
            .animation(.easeInOut(duration: 0.2), value: isEnabled)
    }

    // added opacity on move hover change
    // and disabled status
    @ViewBuilder
    func MainFrameMod() -> some View {
        if isEnabled {
            MainFrame()
                .opacity(hover ? 1 : 0.8)
                .onHover{ hover = B1a2a1b }
        } else {
            MainFrame()
                .opacity(0.5)
        }
    }

    // Main interface of button
    func MainFrame() -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: 8)
                .fill(Color(hex: 0xD8D8D8))

            configuration.label
                .foregroundColor(.black)
                .font(.custom("SF Pro", size: 18))
        }
    }
}
cngwdvgl

cngwdvgl5#

正如其他开发人员所提到的,SwiftUI的主要思想是用户界面与数据保持同步。您可以通过许多不同的方式执行此操作。这包括@State、@Environment Object、@Binding等。

struct ContentView: View {

    @State private var isEnabled: Bool = false

    var body: some View {
        VStack {
            Button("Press me!") {

            }.disabled(isEnabled)
        }
        .padding()
    }
}

相关问题