代码之家  ›  专栏  ›  技术社区  ›  Sean Stayns Joakim Danielson

ui按钮左对齐图像和居中文本

  •  0
  • Sean Stayns Joakim Danielson  · 技术社区  · 6 年前

    导言:

    我有一个班,它 继承 UIButton . 在这节课上我想 更新 属性,例如 titleEdgeInsets , imageEdgeInsets , contentHorizontalAlignment .

    我的第一个方法是 layoutSubviews :

    override func layoutSubviews() {
        super.layoutSubviews()
    
        // update properties 
    }
    

    这个 布局子视图 创建一个 无限环路 ,这样我就找到了另一种方法。

    我的问题:

    使用 willMove 方法 更新 乌布顿 属性?

    override func willMove(toWindow newWindow: UIWindow?) {
        super.willMove(toWindow: newWindow)
    
        // update properties
    }
    

    如果不是,为什么?

    我的目标是左对齐按钮的图像视图(带填充)并将文本居中。

    更新:

    我需要按钮frame.size和bounds.width来计算文本和图像视图的位置

    1 回复  |  直到 6 年前
        1
  •  1
  •   Sandeep Bhandari    6 年前

    上面提到的所有属性都可以在 init UIButton 完全没有必要把它们放进去 layoutSubviews willMove(toWindow . 布局子视图 将被多次调用,因此在此处再次设置这些属性毫无意义。 将移动(Towindow 当按钮添加到某个视图并加载按钮时将调用,但您不必等到那时才能设置这些属性。因为你已经有了button的子类,所以我建议你做

    class SomeButton: UIButton {
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            self.contentHorizontalAlignment = .center
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    }
    

    通过创建 乌布顿 不建议这样做,因此如果您只想将这些属性分配给按钮,您可以扩展到 乌布顿

    extension UIButton {
        func applyStyle() {
            self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            self.contentHorizontalAlignment = .center
        }
    }
    

    编辑:

    这就是你想要的吗??

    enter image description here

    enter image description here

    不管文本是什么,文本总是在中间,图像是在它的左边,有10个像素的填充。

    编辑2:

    正如OP已经确认的那样,他希望按钮的样式如上图所示,发布代码以实现相同的效果。

    class SomeButton: UIButton {
        var titleFont: UIFont! = nil
        var textSize: CGFloat = 0
        let imageWidth: CGFloat = 20
        let buttonHeight: CGFloat = 30
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.titleFont = titleLabel!.font
            self.setTitle("here", for: .normal)
            self.setTitleColor(UIColor.red, for: .normal)
            self.setImage(UIImage(named: "hand"), for: .normal)
            self.backgroundColor = UIColor.green
        }
    
        override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
            if let string = self.title(for: .normal) {
                textSize = string.widthOfString(usingFont: self.titleFont)
                //30 because imageWidth + 10 padding
                return CGRect(origin: CGPoint(x: 30, y: 0), size: CGSize(width: textSize + 30, height: buttonHeight))
            }
            return CGRect.zero
        }
    
        override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
            return CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: imageWidth, height: buttonHeight))
        }
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override var intrinsicContentSize: CGSize {
            //60 because you need eauql padding on both side 30 + 30 = 60
            return CGSize(width: textSize + 60, height: buttonHeight)
        }
    }
    
    extension String {
    
        func widthOfString(usingFont font: UIFont) -> CGFloat {
            let fontAttributes = [NSAttributedString.Key.font: font]
            let size = self.size(withAttributes: fontAttributes)
            return size.width
        }
    }
    

    希望它有帮助