// // StyleButton.swift // Crush // // Created by Leon on 2025/7/17. // import SwiftyAttributes import UIKit enum StyleButtonSize { /// height: 32, tls case small /// height: 40, tlm case medium /// height: 48, tll case large } class StyleButton: CLButton { var radius: CGFloat = 0 private var enableBorderColor: UIColor? private var disableBorderColor: UIColor? private var pressBorderColor: UIColor? var text: String? { didSet { setTitle(text, for: .normal) } } var titleColor: UIColor? { didSet { setTitleColor(titleColor, for: .normal) } } override var isEnabled: Bool { didSet { if let enableColor = enableBorderColor, let disableColor = disableBorderColor { layer.borderColor = isEnabled ? enableColor.cgColor : disableColor.cgColor } } } override var isHighlighted: Bool { didSet { if let enableColor = enableBorderColor, let pressColor = pressBorderColor { layer.borderColor = isHighlighted ? pressColor.cgColor : enableColor.cgColor } } } override init(frame: CGRect) { super.init(frame: frame) backgroundColor = nil tintColor = nil contentMode = .scaleAspectFill titleLabel?.setContentHuggingPriority(UILayoutPriority(248), for: .horizontal) //setContentHuggingPriority(UILayoutPriority(248), for: .horizontal) setContentCompressionResistancePriority(UILayoutPriority(755), for: .horizontal) titleLabel?.adjustsFontSizeToFitWidth = true constraints.forEach { if $0.firstAttribute == .height { removeConstraint($0) } } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - Style Buttons public func primary(size: StyleButtonSize) { setTitleColor(.c.ctpn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.ctpn, for: .highlighted) // var configuration = UIButton.Configuration.plain() // configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 32, bottom: 0, trailing: 32) // self.configuration = configuration // 设置状态更新处理 // configurationUpdateHandler = { [weak self] button in // guard self != nil else { return } // var updatedConfig = button.configuration ?? UIButton.Configuration.plain() // // // 根据按钮状态设置不同的背景图片 // switch button.state { // case .normal: // let gradient = CLSystemToken.gradient(token: .cpgn) // let normalBg = gradient.toImage(size: .init(width: 40, height: 10)) // updatedConfig.background.image = normalBg // updatedConfig.background.imageContentMode = .scaleAspectFill // case .highlighted: // let highlight = CLSystemToken.gradient(token: .cpgp) // let pressBg = highlight.toImage(size: .init(width: 40, height: 10)) // updatedConfig.background.image = pressBg // updatedConfig.background.imageContentMode = .scaleAspectFill // case .disabled: // let disabledImage = UIImage.withColor(color: .c.cpd, size: .init(width: 20, height: 20)) // updatedConfig.background.image = disabledImage // updatedConfig.background.imageContentMode = .scaleAspectFill // default: // let gradient = CLSystemToken.gradient(token: .cpgn) // let normalBg = gradient.toImage(size: .init(width: 40, height: 10)) // updatedConfig.background.image = normalBg // } // // button.configuration = updatedConfig // } let gradient = CLSystemToken.gradient(token: .cpgn) let normalBg = gradient.toImage(size: .init(width: 40, height: 10)) setBackgroundImage(normalBg, for: .normal) let highlight = CLSystemToken.gradient(token: .cpgp) let pressBg = highlight.toImage(size: .init(width: 40, height: 10)) setBackgroundImage(pressBg, for: .highlighted) let disabledImage = UIImage.withColor(color: .c.cpd, size: .init(width: 20, height: 20)) setBackgroundImage(disabledImage, for: .disabled) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } public func tertiary(size: StyleButtonSize) { setTitleColor(.c.ctpn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.ctpn, for: .highlighted) let normalBg = UIImage.withColor(color: .c.csen, size: .init(width: 10, height: 10)) setBackgroundImage(normalBg, for: .normal) let pressBg = UIImage.withColor(color: .c.csep, size: .init(width: 10, height: 10)) setBackgroundImage(pressBg, for: .highlighted) let disabledImage = UIImage.withColor(color: .c.csed, size: .init(width: 10, height: 10)) setBackgroundImage(disabledImage, for: .disabled) commonDealSize(size: size) commonDealSpacing(size: size) setNeedsDisplay() layoutIfNeeded() } public func defaultSecondary(size: StyleButtonSize) { setTitleColor(.c.cpvn, for: .normal) setTitleColor(.c.ctd, for: .disabled) setTitleColor(.c.cpvp, for: .highlighted) enableBorderColor = .c.cpvn disableBorderColor = .c.cpvd pressBorderColor = .c.cpvp layer.borderWidth = CLSystemToken.border(token: .bs) isEnabled = true radius = CLSystemToken.radius(token: .rp) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } public func defaultDestructive(size: StyleButtonSize) { setTitleColor(.c.ctpn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.ctpn, for: .highlighted) // iOS 15+设置方法 // var configuration = UIButton.Configuration.plain() // configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 32, bottom: 0, trailing: 32) // self.configuration = configuration // // // 设置状态更新处理 // configurationUpdateHandler = { [weak self] button in // guard self != nil else { return } // var updatedConfig = button.configuration ?? UIButton.Configuration.plain() // // // 根据按钮状态设置不同的背景图片 // switch button.state { // case .normal: // let normalBg = UIImage.withColor(color: .c.cin, size: .init(width: 10, height: 10)) // updatedConfig.background.image = normalBg // updatedConfig.background.imageContentMode = .scaleAspectFill // case .highlighted: // let pressBg = UIImage.withColor(color: .c.cip, size: .init(width: 10, height: 10)) // updatedConfig.background.image = pressBg // updatedConfig.background.imageContentMode = .scaleAspectFill // case .disabled: // let disabledImage = UIImage.withColor(color: .c.cid, size: .init(width: 10, height: 10)) // updatedConfig.background.image = disabledImage // updatedConfig.background.imageContentMode = .scaleAspectFill // default: // let gradient = CLSystemToken.gradient(token: .cin) // let normalBg = gradient.toImage(size: .init(width: 40, height: 10)) // updatedConfig.background.image = normalBg // } // // button.configuration = updatedConfig // } let normalBg = UIImage.withColor(color: .c.cin, size: .init(width: 10, height: 10)) setBackgroundImage(normalBg, for: .normal) let pressBg = UIImage.withColor(color: .c.cip, size: .init(width: 10, height: 10)) setBackgroundImage(pressBg, for: .highlighted) let disabledImage = UIImage.withColor(color: .c.cid, size: .init(width: 10, height: 10)) setBackgroundImage(disabledImage, for: .disabled) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } /// 渐变主题色 button public func context(size: StyleButtonSize) { setTitleColor(.c.csbn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.csbp, for: .highlighted) // let c = UIColor.c.ccvn let gradient = CLSystemToken.gradient(token: .ccvn) let normalBg = gradient.toImage(size: CGSize(width: 40, height: 10)) setBackgroundImage(normalBg, for: .normal) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } public func vip(size: StyleButtonSize){ setTitleColor(.c.csbn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.csbp, for: .highlighted) let gradient = CLSystemToken.gradient(token: .ccvn) let normalBg = gradient.toImage(size: CGSize(width: 40, height: 10)) setBackgroundImage(normalBg, for: .normal) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } public func text(size: StyleButtonSize){ setTitleColor(.c.cpvn, for: .normal) setTitleColor(.c.ctd, for: .disabled) setTitleColor(.c.cpvp, for: .highlighted) setBackgroundImage(nil, for: .normal) commonDealSize(size: size) commonDealSpacing(size: size) layoutIfNeeded() } public func contrastTertiaryLight(size: StyleButtonSize){ setTitleColor(.c.ctpn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.ctpn, for: .highlighted) let normalBg = UIImage.withColor(color: .c.cseln, size: .init(width: 10, height: 10)) setBackgroundImage(normalBg, for: .normal) let pressBg = UIImage.withColor(color: .c.cselp, size: .init(width: 10, height: 10)) setBackgroundImage(pressBg, for: .highlighted) let disabledImage = UIImage.withColor(color: .c.cseld, size: .init(width: 10, height: 10)) setBackgroundImage(disabledImage, for: .disabled) commonDealSize(size: size) commonDealSpacing(size: size) setNeedsDisplay() layoutIfNeeded() } public func contrastTertiaryDark(size: StyleButtonSize){ setTitleColor(.c.ctpn, for: .normal) setTitleColor(.c.ctpd, for: .disabled) setTitleColor(.c.ctpn, for: .highlighted) let normalBg = UIImage.withColor(color: .c.csedn, size: .init(width: 10, height: 10)) setBackgroundImage(normalBg, for: .normal) let pressBg = UIImage.withColor(color: .c.csedp, size: .init(width: 10, height: 10)) setBackgroundImage(pressBg, for: .highlighted) let disabledImage = UIImage.withColor(color: .c.csedd, size: .init(width: 10, height: 10)) setBackgroundImage(disabledImage, for: .disabled) commonDealSize(size: size) commonDealSpacing(size: size) setNeedsDisplay() layoutIfNeeded() } // MARK: - Common private func commonDealSize(size: StyleButtonSize) { switch size { case .small: let typography = CLSystemToken.typography(token: .tls) titleLabel?.font = typography.font snp.makeConstraints { make in make.height.equalTo(32) } case .medium: let typography = CLSystemToken.typography(token: .tlm) titleLabel?.font = typography.font snp.makeConstraints { make in make.height.equalTo(40) } case .large: let typography = CLSystemToken.typography(token: .tll) titleLabel?.font = typography.font snp.makeConstraints { make in make.height.equalTo(48) } } } private func commonDealSpacing(size: StyleButtonSize) { switch size { case .small: contentEdgeInsets = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) // var configuration = self.configuration ?? UIButton.Configuration.plain() // configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16) // self.configuration = configuration case .medium: contentEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) // var configuration = self.configuration ?? UIButton.Configuration.plain() // configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20) // self.configuration = configuration case .large: contentEdgeInsets = UIEdgeInsets(top: 0, left: 32, bottom: 0, right: 32) // var configuration = self.configuration ?? UIButton.Configuration.plain() // configuration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 32, bottom: 0, trailing: 32) // self.configuration = configuration } } // MARK: layout override func layoutSubviews() { super.layoutSubviews() if radius >= 1 { layer.cornerRadius = radius } else { layer.cornerRadius = bounds.size.height * 0.5 } layer.masksToBounds = true } }