美文网首页
iOS15 UIButton configuration

iOS15 UIButton configuration

作者: 564a | 来源:发表于2022-02-24 14:35 被阅读0次

直接上代码,看注释

let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.addTarget(self, action: #selector(filterConditionSelectAction(btn:)), for: .touchUpInside)
if #available(iOS 15.0, *) {
    // 初始化一个configuration,有多种方法,可根据需要选择
    btn.configuration = UIButton.Configuration.plain()
    // title 和 subtitle的对其关系,文本是上下排版的
    btn.configuration?.titleAlignment = .leading
    // title he subtitle的间距
    btn.configuration?.titlePadding = 16.scaleToScreen()
    // image 和 文本 的相对位置
    btn.configuration?.imagePlacement = .trailing
    // image 和 文本的间距
    btn.configuration?.imagePadding = 16.scaleToScreen()
    // button的内容(title,subtitle,image)显示后与按钮的边距,默认由一段距离
    btn.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
    // 设置按钮的状态变化的监听,根据变化来改变按钮的显示内容,之前都是全部设置进去自动切换的,现在不行了
    btn.configurationUpdateHandler = {(button: UIButton) -> Void in
        //根据状态修改内容
        switch button.state {
        case .normal, .highlighted:
            // image变化
            button.configuration?.image = UIImage.arrowPickUp
            // 背景的变化,默认会有些自带效果,
            button.configuration?.background.backgroundColor = .clear
            // 字体的样式与之前一样
            button.configuration?.attributedTitle = AttributedString(title, attributes: AttributeContainer([
                NSAttributedString.Key.font : UIFont.customMediumFont(ofSize: UIFont.sizeL),
                NSAttributedString.Key.foregroundColor : UIColor.whiteAlpha50 ?? .red]))
            // 子标题,iOS15之后才有,对应的button.subtitleLabel
            button.configuration?.subtitle = "abc"

        case .selected, [.selected, .highlighted]:
            // image变化,与上面对应
            button.configuration?.image = UIImage.arrowUnfold

        case .disabled:
            Log.Debug(message: "不可\(btn.state)")
        default:
            Log.Debug(message: "默认值\(btn.state)")
        }
        button.updateConfiguration()
        
    }
} else {
    // iOS15 之前的属性设置
    btn.setTitle(title, for: .normal)
    // 字体颜色
    btn.setTitleColor(UIColor.whiteAlpha50, for: .normal)
    btn.setTitleColor(UIColor.whiteAlpha50, for: .selected)
    // 设置图片各种状态都需要设置
    btn.setImage(UIImage.arrowUnfold, for: .normal)
    btn.setImage(UIImage.arrowUnfold, for: .highlighted)
    btn.setImage(UIImage.arrowPickUp, for: .selected)
    btn.setImage(UIImage.arrowPickUp, for: [.selected, .highlighted])
    btn.titleLabel?.font = UIFont.customFont(ofSize: UIFont.sizeL)
    // 改变title与image的位置关系
    btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -15.scaleToScreen(), bottom: 0, right: 15.scaleToScreen())
    btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 51.scaleToScreen(), bottom: 0, right: -51.scaleToScreen())
    btn.backgroundColor = .gray
}
view.addSubview(btn)

按钮的内部布局控制比之前简单很多,不像之前,简单的 可以通过titleEdgeInsets 和 imageEdgeInsets来处理,复杂的就需要自定了,

自定义demo

import UIKit

public enum CustomButtonLayoutType : Int {
    case system
    case imageTop
    case imageRight
    case avatar
}

public class CustomButton: UIButton {
    
    public var cusFont: UIFont? {
        get {
            return self.titleLabel?.font
        }
        set {
            self.titleLabel?.font = newValue
        }
    }
    
    public var layoutType: CustomButtonLayoutType = .system
    
    override public func titleRect(forContentRect contentRect: CGRect) -> CGRect {
        
        if layoutType == .system || contentRect == CGRect.zero {
            return super.titleRect(forContentRect: contentRect)
        }
        let imageSize = super.imageRect(forContentRect: contentRect)
        let titleSize = calculateTitleSize(size: contentRect.size)
        
        switch layoutType {
        case .imageTop:
            let x = (contentRect.width - titleSize.width) / 2 + contentRect.minX + self.titleEdgeInsets.left
            let y = (contentRect.height + imageSize.height - titleSize.height) / 2 + contentRect.minY + self.titleEdgeInsets.top
            return CGRect(x: x, y: y, width: titleSize.width, height: titleSize.height)
            
        case .imageRight:
            let x = (contentRect.width - imageSize.width - titleSize.width) / 2 + contentRect.minX + self.titleEdgeInsets.left
            let y = (contentRect.height - titleSize.height) / 2 + contentRect.minY + self.titleEdgeInsets.top
            return CGRect(x: x, y: y, width: titleSize.width, height: titleSize.height)
            
        default:
            return super.titleRect(forContentRect: contentRect)
        }
    }
    
    override public func imageRect(forContentRect contentRect: CGRect) -> CGRect {
        if layoutType == .system || contentRect == CGRect.zero{
            return super.imageRect(forContentRect: contentRect)
        }
        
        let imageSize = super.imageRect(forContentRect: contentRect)
        let titleSize = calculateTitleSize(size: contentRect.size)
        
        switch layoutType {
        case .imageTop:
            let x = (contentRect.width - imageSize.width) / 2 + contentRect.minX + self.imageEdgeInsets.left
            let y = (contentRect.height - imageSize.height - titleSize.height) / 2 + contentRect.minY + self.imageEdgeInsets.top
            return CGRect(x: x, y: y, width: imageSize.width, height: imageSize.height)
            
        case .imageRight:
            let x = (contentRect.width + titleSize.width - imageSize.width) / 2 + contentRect.minX + self.imageEdgeInsets.left
            let y = (contentRect.height - imageSize.height) / 2 + contentRect.minY + self.imageEdgeInsets.top
            return CGRect(x: x, y: y, width: imageSize.width, height: imageSize.height)
            
        case .avatar:
            let bgImageWidth: CGFloat = self.currentBackgroundImage?.size.width ?? imageSize.width
            let width: CGFloat = imageSize.width * contentRect.width / bgImageWidth
            let height = width * imageSize.height / imageSize.width
            let x = (contentRect.width - width) + contentRect.minX + self.imageEdgeInsets.left
            let y = (contentRect.height - height) + contentRect.minY + self.imageEdgeInsets.top
            return CGRect(x: x, y: y, width: width, height: height)
        default:
            return super.imageRect(forContentRect: contentRect)
        }
    }
    
    override public func backgroundRect(forBounds bounds: CGRect) -> CGRect {
        return super.backgroundRect(forBounds: bounds)
    }
    
    private func calculateTitleSize(size: CGSize) -> CGSize {
        if let title = self.currentAttributedTitle {
            return title.size()
        }
        if let title = self.currentTitle {
            let options: NSStringDrawingOptions = .usesLineFragmentOrigin
            let attributes : [NSAttributedString.Key : Any] = [.font: cusFont ?? UIFont.customFont(ofSize: UIFont.size1xl)]
            return title.boundingRect(with: size, options: options, attributes: attributes, context: nil).size
        }
        return CGSize.zero
    }

}

相关文章

网友评论

      本文标题:iOS15 UIButton configuration

      本文链接:https://www.haomeiwen.com/subject/tgmzlrtx.html