美文网首页iOS之Swift功能细节Swift好文收藏
Swift UIButton EdgeInsets修改成左文右图

Swift UIButton EdgeInsets修改成左文右图

作者: 34码的小孩子 | 来源:发表于2018-02-02 14:10 被阅读4次

    UIButton默认是左图右文的形式,但是有时候我们需要左文右图、上文下图、上图下文等形式。
    下面会根据UIButton的titleEdgeInsets 和 imageEdgeInsets 这两个属性,将按钮修改成我们需要的样子。

    理解

    首先我们先看一下UIEdgeInsets定义

    Edge inset values are applied to a rectangle to shrink or expand the area represented by that rectangle. Typically, edge insets are used during view layout to modify the view’s frame. Positive values cause the frame to be inset (or shrunk) by the specified amount. Negative values cause the frame to be outset (or expanded) by the specified amount.

    edge inset 用来缩小或者是扩大View显示的区域。通常是在View layout 的时候修改view的frame。正值表示缩小,负值表示扩大。
    在我的理解中,如果想要移动准确的距离,左右或者上下都需要设置相同的值,只是一负一正,正好是一边缩小frame, 一边扩大frame。

    在默认的模式下,这两个属性的值是UIEdgeInsetsZero 而我们的修改也是在这个基础上的,所以我们需要根据默认的左图右文来看看,究竟要怎么修改。

    左文右图

    左文右图调整

    先来看图标icon,从左侧转变到右侧,就需要向右移动X3- X2的距离,就是title的宽度。而title从右侧移动到左侧,则需要向左移动 X2 - X1的距离,也就是icon的宽度。

    self.titleEdgeInsets = UIEdgeInsetsMake(0, -imageSize.width, 0, imageSize.width)
    self.imageEdgeInsets = UIEdgeInsetsMake(0, titleWidth, 0, -titleWidth)
    

    上图下文和上文下图

    中间变换图

    假设左文右图icon的左边坐标X = 0

    X3 = (iconWidth + titleWidth) / 2
    X1 = iconWidth / 2
    X2 = iconWidth + titleWidth / 2
    

    所以,从icon 需要向右移动 X3 - X1 = titleWidth / 2; title需要向左移动 X2 - X3 = iconWidth / 2

    上图下文

    假设上文下图中icon的顶部top的坐标y = 0

    y1 = (iconHeight + titleHeight) / 2
    y2 = iconHeight / 2
    y3 = iconHeight + titleHeight / 2
    

    所以,icon需要向上移动 y1 - y2 = titleHeight / 2; title需要向下移动 y3 - y2 = iconHeight / 2
    结合起来,从左图右文到上图下文:

    self.titleEdgeInsets = UIEdgeInsetsMake(imageSize.height / 2, -imageSize.width / 2, -imageSize.height / 2, imageSize.width / 2)
    self.imageEdgeInsets = UIEdgeInsetsMake(-titleHeight / 2, titleWidth / 2, titleHeight / 2, -titleWidth / 2)
    

    同理:


    上文下图
    self.titleEdgeInsets = UIEdgeInsetsMake(-imageSize.height / 2, 0, imageSize.height / 2, imageSize.width)
    self.imageEdgeInsets = UIEdgeInsetsMake(titleHeight / 2, titleWidth / 2, -titleHeight / 2, -titleWidth / 2)
    

    应用

    为了方便使用,我选择扩展UIButton。代码如下:

    extension UIButton {
    enum ButtonEdgeInsetType {
        case normal                 // 左图右文
        case leftTitleRightImage    // 左文右图
        case topImageBottomTitle    // 上图下文
        case topTitleBottomImage    // 上文下图
    }
    
    func changeButtonType(into type: ButtonEdgeInsetType) {
        if self.currentTitle == nil || self.currentImage == nil {
            // 没有标题或者是图片,会居中显示,不需要修改。
            return
        }
        
        // 不能直接使用self.titleLabel.bounds.size来获取宽高,此时,bounds还没有值,需要计算
        let titleWidth = Constant.getLabelWidth(with: self.currentTitle, font: (self.titleLabel?.font)!, height: 21)
        let titleHeight = Constant.getLabelHeight(with: self.currentTitle, font: (self.titleLabel?.font)!, width: titleWidth)
        let imageSize = (self.currentImage?.size)!
    
        switch type {
        case .leftTitleRightImage:
            self.titleEdgeInsets = UIEdgeInsetsMake(0, -imageSize.width, 0, imageSize.width)
            self.imageEdgeInsets = UIEdgeInsetsMake(0, titleWidth, 0, -titleWidth)
        case .topImageBottomTitle:
            self.titleEdgeInsets = UIEdgeInsetsMake(imageSize.height / 2, -imageSize.width / 2, -imageSize.height / 2, imageSize.width / 2)
            self.imageEdgeInsets = UIEdgeInsetsMake(-titleHeight / 2, titleWidth / 2, titleHeight / 2, -titleWidth / 2)
        case .topTitleBottomImage:
            self.titleEdgeInsets = UIEdgeInsetsMake(-imageSize.height / 2, 0, imageSize.height / 2, imageSize.width)
            self.imageEdgeInsets = UIEdgeInsetsMake(titleHeight / 2, titleWidth / 2, -titleHeight / 2, -titleWidth / 2)
        default:
            // 默认是左图右文,也不需要做任何修改。
            break
        }
    }
    }
    

    需要注意的是,如果在方法中,直接使用self.titleLabel.bounds.size来获取title的宽高,是不可行的。试过断点,发现获取到的宽高都是0, 应该是titleLabel的frame还没有进行赋值。
    我觉得可以这样子理解,我们设置titleEdgeInsets 就是要在layout的时候改变title的frame,frame 应该是在我们设置了之后才会确定。但感觉又不太对,如果你们有更好的解释,请留言。
    下面是获取title的宽高的方法:

    static func getLabelWidth(with content: String?, font: UIFont, height: CGFloat) -> CGFloat {
        if content == nil || (content?.count)! <= 0 {
            return 0
        }
        
        let size = CGSize.init(width: CGFloat(MAXFLOAT), height: height)
        let nsContent = content! as NSString
        let returnSize = nsContent.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: [NSAttributedStringKey.font: font], context: nil)
        
        return returnSize.width
    }
    
    static func getLabelHeight(with content: String?, font: UIFont, width: CGFloat) -> CGFloat {
        if content == nil || (content?.count)! <= 0 {
            return 0
        }
        
        let size = CGSize.init(width: width, height: CGFloat(MAXFLOAT))
        let nsContent = content! as NSString
        let returnSize = nsContent.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: [NSAttributedStringKey.font: font], context: nil)
        
        return returnSize.height
    }
    

    需要修改样式的时候,只需要一行代码就搞定了。

    let yearButton = UIButton.init(type: .custom)
    yearButton.frame = CGRect.init(x: (Constant.ScreenWidth - buttonWidth) / 2, y: 20, width: buttonWidth, height: 64 - 20)
    yearButton.setTitle("2018", for: .normal)
    yearButton.setImage(UIImage.init(named: "home_dropdown_icon"), for: .normal)
    
    // 传说中的一行代码,啊哈哈哈哈😆😆😆😆
    yearButton.changeButtonType(into: .topTitleBottomImage)
    

    欢迎大家来吐槽~~~

    相关文章

      网友评论

        本文标题:Swift UIButton EdgeInsets修改成左文右图

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