I have a UIButton
that I add to my view controller\'s view in a storyboard. I add centering constraints to position it and leading space constraints to limit it
Override the -(CGSize)intrinsicContentSize in Custom UIButton as given below.
Objective - C:
-(CGSize)intrinsicContentSize {
CGSize titleLabelIntrinsicSize = [self.titleLabel intrinsicContentSize];
return CGSizeMake(titleLabelIntrinsicSize.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right, titleLabelIntrinsicSize.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom);
}
Swfit :
override var intrinsicContentSize: CGSize {
get {
if let thisSize = self.titleLabel?.intrinsicContentSize {
return CGSize(width: thisSize.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right, height: thisSize.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom)
}
return super.intrinsicContentSize
}
}
Got same issue. It happens only if UIButton
's titleLabel
has more than one line. Is it a bug in UIKit?
My Swift solution:
class ResizableButton: UIButton {
override var intrinsicContentSize: CGSize {
let labelSize = titleLabel?.sizeThatFits(CGSize(width: frame.size.width, height: CGFloat.greatestFiniteMagnitude)) ?? .zero
let desiredButtonSize = CGSize(width: labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
return desiredButtonSize
}
}
I am away from my computer so I can't add the code right now, but I have found a workaround of this before.
What you can do is create a UILabel
and add a UITapGestureRecognizer
to the label. Do whatever you want for the button's action by handling the tap event. And also make sure that you enable user interactions on the UILabel
.
This label will now behave as a auto resizing button.
I had to invalidate the intrinsic content size when the views were laid out and then calculate the height of the button for the intrinsicContentSize property.
Here's the code in Swift3/Xcode 9
override func layoutSubviews() {
self.invalidateIntrinsicContentSize()
super.layoutSubviews()
}
override var intrinsicContentSize: CGSize {
return CGSize(width: self.frame.size.width, height: titleLabel!.frame.size.height + contentEdgeInsets.top + contentEdgeInsets.bottom)
}
I struggled with this for a while and ended up making it work by subclassing UIButton and adding these two functions
class GoalsButton: UIButton {
override var intrinsicContentSize: CGSize {
return self.titleLabel!.intrinsicContentSize
}
// Whever the button is changed or needs to layout subviews,
override func layoutSubviews() {
super.layoutSubviews()
titleLabel?.preferredMaxLayoutWidth = self.titleLabel!.frame.size.width
}
}
[self.button sizeToFit] should work if your Autolayout is turned Off. If you have to use autolayout then other suggestions (calculating line width) etc are more appropriate.