【问题标题】:SwiftUI: Optimal way to disable NavigationLink which has a custom ButtonStyleSwiftUI:禁用具有自定义 ButtonStyle 的 NavigationLink 的最佳方法
【发布时间】:2020-11-14 18:39:49
【问题描述】:

我有一个具有自定义 ButtonStyle 的导航链接:

NavigationLink(destination: NextScreen()) {
   Text("Next")
}
.buttonStyle(CustomButtonStyle(disabled: !isValidPassword))

我的 CustomButtonStyle 看起来像这样:

@State var disabled = false
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding(15)
            .foregroundColor(.white)
            .background(disabled ? .black : .gray)
            .cornerRadius(40)
            .disabled(disabled) // this has no effect when inside a NavigationLink
    }

用户输入密码时,用户界面会正确更新。 您可以看到我禁用了 ButtonStyle 内的按钮,但这并不妨碍用户仍然点击 NavigationLink 以转到 NextScreen()。 为了解决这个问题,我最终这样做了:

NavigationLink(destination: SignupStepBirthdayView()) {
    Text("Next")
}
.buttonStyle(BobbleUpButtonStyle(disabled: !isValidPassword))
.disabled(!isValidPassword)

这似乎效率低下,因为我将禁用状态传递给按钮样式以更新 UI,然后不得不禁用实际的 NavigationLink。 有没有更好的方法来做到这一点?

【问题讨论】:

  • ButtonStyle 是关于按钮的视觉呈现(在这种情况下是链接),而不是关于行为。通过自定义样式,您禁用了 NavigationLink 内的文本标签,而不是链接本身 - 它应该在外部禁用,就像您已经做的那样。

标签: swift swiftui swiftui-navigationlink


【解决方案1】:

我将向您展示简单的方法,无需使用@Bingding 或@State

  1. 首先,创建您的按钮样式:

    struct CustomButtonStyle: ButtonStyle {
    
        public 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
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .padding(15)
                    .foregroundColor(.white)
                    .background(isEnabled ? Color.blue : Color.gray)
                    .cornerRadius(40)
                    .disabled(!isEnabled)
            }    
        }
    }
    
  2. 然后,将其作为任何 SwiftUI 组件禁用:

    struct ContentView: View {
    
        @State var text: String = ""
    
        var body: some View {
            NavigationView {
                VStack {
                    TextField("Enter your text", text: $text)
                    NavigationLink(destination: NextScreen()) {
                       Text("Next")
                    }
                    .buttonStyle(CustomButtonStyle())
                    .disabled(text.isEmpty)
                }
            }
        }
    }
    

【讨论】:

    【解决方案2】:

    您必须在 CustomButtonStyle 中使用 Binding 而不是 State

    @Binding var disabled : Bool
    

    这会在您的 ContentView 中发生变化

    @State var isValidPassword: Bool = true
    

    还有:

    .buttonStyle(BobbleUpButtonStyle(disabled: $isValidPassword))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多