UIButtonresize以适应titleLabel

我有一个UIButton,我添加到故事板中的视图控制器视图。 我添加了居中约束来定位它,并引导空间约束来限制它的宽度。 在代码中我添加:

self.button.titleLabel.numberOfLines = 0; self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; [self.button setTitle:@"A real real real real real real real real long long name." forState:UIControlStateNormal]; self.button.backgroundColor = [UIColor redColor]; self.button.titleLabel.backgroundColor = [UIColor blueColor]; 

结果如下所示:

在这里输入图像说明

我想要button来调整其内容。 我怎样才能做到这一点?

我试过了

[self.button sizeToFit];

我已经尝试将内容拥抱和压缩阻力自动布局约束优先级设置为需要。

我也试着明确地设置contentEdgeInsets和titleEdgeInsets到UIEdgeInsetsZero并调用invalidateIntrinsicContentsize。

我也注意到,如果我在标题string中放置换行符,button似乎resize以适应其内容。

我在iPhone 6模拟器上运行Xcode 6和iOS 8。

我已经得到这个工作,但你必须使用自定义button,而不是一个系统types。 给button的宽度和高度的约束,并作出一个IBOutlet的高度约束(heightCon在我的代码),所以你可以调整它的代码。

 - (void)viewDidLoad { [super viewDidLoad]; self.button.titleLabel.numberOfLines = 0; self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; [self.button setTitle:@"A real real real real real real real real long long name." forState:UIControlStateNormal]; [self.button addTarget:self action:@selector(doStuff:) forControlEvents:UIControlEventTouchUpInside]; self.button.backgroundColor = [UIColor redColor]; self.button.titleLabel.backgroundColor = [UIColor blueColor]; [self.button layoutIfNeeded]; // need this to update the button's titleLabel's size self.heightCon.constant = self.button.titleLabel.frame.size.height; } 

编辑后:

我发现你也可以更简单地做到这一点,如果你创build一个子类,并使用系统button,并使用此代码,

 @implementation RDButton -(CGSize)intrinsicContentSize { return CGSizeMake(self.frame.size.width, self.titleLabel.frame.size.height); } 

当您设置标题时,将调用覆盖的intrinsicContentSize方法。 在这种情况下,您不应该设置高度限制。

Kubba的答案Swift 3版本:

 class ResizableButton: UIButton { override var intrinsicContentSize: CGSize { let labelSize = titleLabel?.sizeThatFits(CGSize(width: frame.width, height: .greatestFiniteMagnitude)) ?? .zero let desiredButtonSize = CGSize(width: labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom) return desiredButtonSize } } 

有同样的问题。 只有在UIButtontitleLabel才会发生。 这是UIKit中的错误吗?

我的Swift解决scheme:

 class ResizableButton: UIButton { 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 } 

我离开我的电脑,所以我现在不能添加代码,但我已经find了这个解决方法之前。

你可以做的是创build一个UILabel并添加一个UITapGestureRecognizer到标签。 做任何你想要的button的行动通过处理轻敲事件。 还要确保您在UILabel上启用用户交互。

这个标签现在将作为一个自动resize的button。

我苦苦挣扎了一段时间,最后通过inheritanceUIButton并添加这两个函数来完成工作

 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 } } 

我build议的是计算文本的宽度,并自己计算框架。 无论如何,这并不复杂,首先得到文本的宽度:

 [NSString sizeWithFont:font]; 

做一个国防部操作,你会很容易find文本的行数。

请注意,此方法适用于iOS7以上版本,适用于iOS 7以及可能需要尝试的方法

 [NSString sizeWithAttributes:aDictionary]; 

[self.button sizeToFit]应该工作,如果您的Autolayclosures。 如果你必须使用自动布局,那么其他build议(计算线宽)等是更合适的。

我用UIButton与多线文本也有同样的问题,它也有一个图像。 我用sizeThatFits:来计算大小,但它计算错误的高度。

我没有做它UIButtonTypeCustom ,而不是我称为sizeThatFits:在button的titleLabel与较小的宽度(由于按​​钮中的图像)的大小:

 CGSize buttonSize = [button sizeThatFits:CGSizeMake(maxWidth, maxHeight)]; CGSize labelSize = [button.titleLabel sizeThatFits:CGSizeMake(maxWidth - offset, maxHeight)]; // offset for image buttonSize.height = labelSize.height; buttonFrame.size = buttonSize; 

然后我用这个尺寸的高度正确设置button的框架,它工作:)

也许他们在UIButton内部大小上有一些错误。

覆盖自定义UIButton中的 – (CGSize)intrinsicContentSize,如下所示。

目标 – 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 } } 
 class SFResizableButton: UIButton { override var intrinsicContentSize: CGSize { get { var labelSize = CGSize.zero if let text = titleLabel?.text, let font = titleLabel?.font { labelSize.width = text.width(constrained: .greatestFiniteMagnitude, font: font) } else if let att = titleLabel?.attributedText { labelSize.width = att.width(constrained: .greatestFiniteMagnitude) } if let imageView = imageView { labelSize.width = labelSize.width + imageView.frame.width } let desiredButtonSize = CGSize(width: ceil(labelSize.width) + titleEdgeInsets.left + titleEdgeInsets.right + imageEdgeInsets.left + imageEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom + imageEdgeInsets.top + imageEdgeInsets.bottom) return desiredButtonSize } } } extesion String { func width(constrained height: CGFloat, font: UIFont) -> CGFloat { let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height) let boundingBox = (self as NSString).boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil) return boundingBox.width } } extension NSAttributedString { func width(constrained height: CGFloat) -> CGFloat { let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height) let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil) return boundingBox.width } }