swift版 按钮图片左右上下布局+中间距离

2021-03-16  本文已影响0人  授之以渔不如授之以鱼
image.png

意思大家都懂,码来!

import UIKit

extension UIButton {
    
    /// 按钮布局样式
    public enum ButtonLayoutStyle {
        case none, leftImageRightText, rightImageLeftText, topImageBottomText
    }
    
    fileprivate struct AssociatedKeys {
        static var imageTextSpacing: CGFloat = 0.0
        static var layoutStyle: ButtonLayoutStyle = .none
    }
    
    /// 布局样式
    public var layoutStyle: ButtonLayoutStyle {
        get {
            guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.layoutStyle) as? ButtonLayoutStyle else {
                return .none
            }
            return obj
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.layoutStyle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    /// 间隙
    public var imageTextSpacing: CGFloat {
        get {
            guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.imageTextSpacing) as? CGFloat else { return 0 }
            return obj
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.imageTextSpacing, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    /// 计算内部大小(宽高自适应)
    /// 参考:https://github.com/DataDesignSystems/lavoro/blob/02b3090c298c2b4cbea352d9d1adae73eb8022c3/Lavoro/Helpers/UIButton%2BExts.swift
    /// 参考:[关于 UIButton 的 titleEdgeInsets、imageEdgeInsets 及 contentEdgeInsets](https://www.jianshu.com/p/2f0e9150a2a3)
    override open var intrinsicContentSize: CGSize {
        let intrinsicContentSize = super.intrinsicContentSize
        guard self.layoutStyle != .none else {
            return intrinsicContentSize
        }
    
        // 调整边距
        self.adjustInsets()

        // 调整宽度
        let spacing = self.imageTextSpacing
        var contentWidth = intrinsicContentSize.width
        var contentHeight = intrinsicContentSize.height
        switch self.layoutStyle {
        case .leftImageRightText:
            contentWidth += spacing
            contentHeight += (titleEdgeInsets.top - titleEdgeInsets.bottom)
            break
        case .rightImageLeftText:
            contentWidth += spacing
            contentHeight += (titleEdgeInsets.top - titleEdgeInsets.bottom)
            break
        case .topImageBottomText:
            contentHeight += spacing
            contentHeight += (titleEdgeInsets.top + abs(imageEdgeInsets.top)) // 追加撑大高度
            break
        default:
            break
        }

        // 返回内部大小
        return CGSize(width: contentWidth, height: contentHeight)
    }
    
    /// 调整边距 参考:https://github.com/Jyhwenchai/UIButton
    func adjustInsets() {
        
        // Use predefined font, otherwise use the default
        let text = titleLabel?.text ?? ""
        let font: UIFont = titleLabel?.font ?? UIFont()
        let textSize: CGSize = text.size(withAttributes: [NSAttributedString.Key.font: font])
        let imageSize: CGSize = self.imageRect(forContentRect: frame).size
        
        let spacing = self.imageTextSpacing
        let offset = spacing / 2.0

        switch self.layoutStyle {
        case .leftImageRightText: // ---|--- 文字右移,图片左移
            self.titleEdgeInsets = UIEdgeInsets(top: 0, left: offset, bottom: 0, right: -offset)
            self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -offset, bottom: 0, right: offset)
            break
        case .rightImageLeftText: // ---|--- 文字左移,图片右移
            let titleHOffset = imageSize.width
            let imageHOffset = textSize.width

            // 1) 左右布局
            let titleInsets = UIEdgeInsets(top: 0, left: -titleHOffset, bottom: 0, right: titleHOffset)
            let imageInsets = UIEdgeInsets(top: 0, left: imageHOffset, bottom: 0, right: -imageHOffset)
            // 2) 追加间隔
            self.titleEdgeInsets = UIEdgeInsets(top: 0, left: titleInsets.left - offset, bottom: 0, right: titleInsets.right + offset)
            self.imageEdgeInsets = UIEdgeInsets(top: 0, left: imageInsets.left + offset, bottom: 0, right: imageInsets.right - offset)
            break
        case .topImageBottomText: // 文字下移,图片上移
            let titleHOffset = imageSize.width / 2.0
            let imageHOffset = textSize.width / 2.0
            let titleVOffset = imageSize.height / 2.0
            let imageVOffset = textSize.height / 2.0
            // 1) 上下布局
            let titleInsets = UIEdgeInsets(top: titleVOffset, left: -titleHOffset, bottom: -titleVOffset, right: titleHOffset)
            let imageInsets = UIEdgeInsets(top: -imageVOffset, left: imageHOffset, bottom: imageVOffset, right: -imageHOffset)
            // 2) 追加间隔
            self.titleEdgeInsets = UIEdgeInsets(top: titleInsets.top + offset, left: titleInsets.left, bottom: titleInsets.bottom - offset, right: titleInsets.right)
            self.imageEdgeInsets = UIEdgeInsets(top: imageInsets.top - offset, left: imageInsets.left, bottom: imageInsets.bottom + offset, right: imageInsets.right)
            break
        default:
            break
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读