Kex Kex - 4 months ago 14
iOS Question

UIButton failing to resize text correctly for iPhone 4/5 screen sizes. (using intrinsicContentSize)

I have a

UIView
setup in a xib with four buttons in it. The text is left aligned with left edge content inset set to 20 on all of them. The constraints can be seen below:

enter image description here

The xib's width is set to 320 for the width of the iPhone 4 and 5. When this view is added to a view controller I make the frame's width the same as the current screen size e.g. iPhone6 and the buttons will stretch horizontally. Now when I set the title text I want the buttons to grow in height to accommodate the text.

I subclassed UIButton and overrode this method:

override func intrinsicContentSize() -> CGSize {

let labelSize = titleLabel?.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max)) ?? CGSizeZero
let desiredButtonSize = CGSizeMake(labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
return desiredButtonSize
}


I then set the title labels as desired. For the iPhone6 and upwards it works perfectly:

enter image description here

However for the iPhone 4 or 5 I get this result:

enter image description here

Any ideas what I might be doing wrong on this? Would really appreciate some pointers. Thanks!

Answer

I don't think you want to use the button's frame to determine the size the title will fit. You want to use the title's frame. titleLabel?.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max)) will determine the height of the label as though the labels width were the entirety of the button's frame. But you have an inset that will not allow the title to be laid out that way, so it is under estimating the height. This is way your label overflows the bounds of the button. It should be:

    override func intrinsicContentSize() -> CGSize {

        let labelSize = titleLabel?.sizeThatFits(CGSizeMake((self.titleLabel?.frame.size.width)!, CGFloat.max)) ?? CGSizeZero
        let desiredButtonSize = CGSizeMake(labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
        return desiredButtonSize
    }

Edit

Depending on your constraints you may also need

override func layoutSubviews() { 
    super.layoutSubviews() self.titleLabel?.preferredMaxLayoutWidth = self.frame.size.width 
}