按钮不会显示禁用的样式

Posted

技术标签:

【中文标题】按钮不会显示禁用的样式【英文标题】:Button won't show disabled styling 【发布时间】:2021-02-15 18:54:04 【问题描述】:

我创建了一个结构,通过传递类型和大小参数来设置按钮样式。我希望按钮在禁用时更改样式,但它不起作用。该按钮确实在禁用和启用之间切换,但样式始终是启用的样式。

struct CustomButton: ButtonStyle 
    
    enum ButtonStyle 
        case button, destructive, light
    
    enum ButtonSize 
        case normal, large, small
    
    @Environment(\.isEnabled) var isEnabled
    private var maxWidth : CGFloat
    private var padding : CGFloat
    private var foreground : Color
    private var foregroundDisabled : Color
    private var strokeColor : Color
    private var strokeDisabled : Color
    private var strokeWidth : CGFloat
    private var background : Color
    private var backgroundDisabled : Color
    private var fontSize : Font
    
    init(style: ButtonStyle, size: ButtonSize) 
        switch size 
        case .large:
            self.maxWidth = .infinity
            self.padding = 15.0
            self.fontSize = Font.system(.title3, design: .rounded).weight(.bold)
        case .small:
            self.maxWidth = 200
            self.padding = 8.0
            self.fontSize = Font.system(.callout, design: .rounded)
        default:
            self.maxWidth = .infinity
            self.padding = 12.0
            self.fontSize = Font.system(.body, design: .rounded)
        
        
        switch style 
        case .light:
            strokeColor = .main
            strokeDisabled = .gray
            strokeWidth = size == .small ? strokeSmall: strokeLarge
            foreground = .main
            foregroundDisabled = .gray
            background = .clear
            backgroundDisabled = .clear
        case .destructive:
            strokeColor = .destructive
            strokeDisabled = .gray
            strokeWidth = size == .small ? strokeSmall : strokeLarge
            foreground = .destructive
            foregroundDisabled = .destructive
            background = .clear
            backgroundDisabled = .clear
        default:
            strokeColor = .clear
            strokeDisabled = .clear
            strokeWidth = 0.0
            foreground = .white
            foregroundDisabled = .white
            backgroundDisabled = .gray
            background = .main
        
    
    
    func makeBody(configuration: Self.Configuration) -> some View 
        return configuration.label
            .frame(maxWidth: maxWidth)
            .font(fontSize)
            .foregroundColor(isEnabled ? foreground : Color.red)
            .padding(padding)
            .background(RoundedRectangle(cornerRadius: roundedCorner)
                .strokeBorder(isEnabled ? strokeColor : strokeDisabled, lineWidth: strokeWidth)
                .background(isEnabled ? background : backgroundDisabled)
            )
            .clipShape(RoundedRectangle(cornerRadius: roundedCorner))
            .opacity(configuration.isPressed ? 0.8 : 1.0)
            .scaleEffect(configuration.isPressed ? 0.98 : 1.0)
    

它被添加到这样的视图中:

Button(action:    
   //Some logic here
, label: 
    Text(NSLocalizedString("Add Group", comment: "button"))
)
.disabled(selections.count < 2) //the button does become disabled (but doesn't change style)
.buttonStyle(CustomButton(style: .button, size: .normal))

【问题讨论】:

这个帖子有帮助吗? ***.com/questions/59169436/… 【参考方案1】:

@Environment 没有注入样式,它仅用于视图,所以这里有一个可能的解决方案演示 - 基于内部帮助包装器视图。

struct CustomButton: ButtonStyle 

    enum ButtonStyle 
        case button, destructive, light
    
    enum ButtonSize 
        case normal, large, small
    

    private var maxWidth : CGFloat
    private var padding : CGFloat
    private var foreground : Color
    private var foregroundDisabled : Color
    private var strokeColor : Color
    private var strokeDisabled : Color
    private var strokeWidth : CGFloat
    private var background : Color
    private var backgroundDisabled : Color
    private var fontSize : Font

    init(style: ButtonStyle, size: ButtonSize) 
        switch size 
        case .large:
            self.maxWidth = .infinity
            self.padding = 15.0
            self.fontSize = Font.system(.title3, design: .rounded).weight(.bold)
        case .small:
            self.maxWidth = 200
            self.padding = 8.0
            self.fontSize = Font.system(.callout, design: .rounded)
        default:
            self.maxWidth = .infinity
            self.padding = 12.0
            self.fontSize = Font.system(.body, design: .rounded)
        

        switch style 
        case .light:
            strokeColor = .main
            strokeDisabled = .gray
            strokeWidth = size == .small ? strokeSmall: strokeLarge
            foreground = .main
            foregroundDisabled = .gray
            background = .clear
            backgroundDisabled = .clear
        case .destructive:
            strokeColor = .destructive
            strokeDisabled = .gray
            strokeWidth = size == .small ? strokeSmall : strokeLarge
            foreground = .destructive
            foregroundDisabled = .destructive
            background = .clear
            backgroundDisabled = .clear
        default:
            strokeColor = .clear
            strokeDisabled = .clear
            strokeWidth = 0.0
            foreground = .white
            foregroundDisabled = .white
            backgroundDisabled = .gray
            background = .main
        
    

    private struct EnvReaderView<Content: View>: View     // << this one !!
        let content: (Bool) -> Content
        @Environment(\.isEnabled) var isEnabled  // read environment
        var body: some View 
            content(isEnabled)  // transfer into builder
        
    

    func makeBody(configuration: Self.Configuration) -> some View 
        EnvReaderView  isEnabled in    // now we can use it !!
            configuration.label
                .frame(maxWidth: maxWidth)
                .font(fontSize)
                .foregroundColor(isEnabled ? foreground : Color.red)
                .padding(padding)
                .background(RoundedRectangle(cornerRadius: roundedCorner)
                                    .strokeBorder(isEnabled ? strokeColor : strokeDisabled, lineWidth: strokeWidth)
                                    .background(isEnabled ? background : backgroundDisabled)
                )
                .clipShape(RoundedRectangle(cornerRadius: roundedCorner))
                .opacity(configuration.isPressed ? 0.8 : 1.0)
                .scaleEffect(configuration.isPressed ? 0.98 : 1.0)
        
    

【讨论】:

以上是关于按钮不会显示禁用的样式的主要内容,如果未能解决你的问题,请参考以下文章

[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]

[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]

[ATL/WTL]_[初级]_[解决自定义按钮禁用时没有绘制自定义样式-显示黑色矩形框的问题]

jQuery 不会在禁用按钮上触发悬停事件吗?

带有 CSS 的样式禁用按钮

jQuery 禁用启用按钮样式