ios 调整大小以适合其 titleLabel 的 UIButton
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27259333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIButton that resizes to fit its titleLabel
提问by Darren
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 its width. In code I add:
我有一个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];
The result is shown below:
结果如下所示:
I want the button to size to its content. How can I do this?
我希望按钮的大小适合其内容。我怎样才能做到这一点?
I've tried
我试过了
[self.button sizeToFit];
and I've tried setting the content hugging and compression resistance autolayout constraints priorities to required.
我已经尝试将内容拥抱和压缩阻力自动布局约束优先级设置为所需。
I've also tried explicitly setting the contentEdgeInsets
and titleEdgeInsets
to UIEdgeInsetsZero
and calling invalidateIntrinsicContentSize
.
我也试着显式设置contentEdgeInsets
,并titleEdgeInsets
以UIEdgeInsetsZero
和调用invalidateIntrinsicContentSize
。
I've also noticed that if I place newline characters in the title string, the button does seem to resize to fit its content.
我还注意到,如果我在标题字符串中放置换行符,按钮似乎会调整大小以适应其内容。
I'm running on Xcode 6 and iOS 8 on the iPhone 6 Simulator.
我在 iPhone 6 模拟器上运行 Xcode 6 和 iOS 8。
采纳答案by rdelmar
I've gotten this to work, but you have to use a custom button, not a system type. Give the button both width and height constraints, and make an IBOutlet to the height constraint (heightCon in my code) so you can adjust it in code.
我已经让它工作了,但你必须使用自定义按钮,而不是系统类型。为按钮提供宽度和高度约束,并为高度约束(我的代码中的 heightCon)创建一个 IBOutlet,以便您可以在代码中对其进行调整。
- (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;
}
After Edit:
编辑后:
I found that you can also do this more simply, and with a system button if you make a subclass, and use this code,
我发现您也可以更简单地执行此操作,如果您创建子类并使用此代码,则使用系统按钮,
@implementation RDButton
-(CGSize)intrinsicContentSize {
return CGSizeMake(self.frame.size.width, self.titleLabel.frame.size.height);
}
The overridden intrinsicContentSize method is called when you set the title. You shouldn't set a height constraint in this case.
当您设置标题时,将调用重写的 internalContentSize 方法。在这种情况下,您不应设置高度约束。
回答by A. Buksha
Swift 4.xversion of Kubba'sanswer:
Kubba答案的Swift 4.x版本:
Need to Update Line Breakas Clip/WordWrap/in Interface builder to corresponding buttons.
需要更新换行作为剪辑/自动换行/在界面生成器相应的按钮。
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
}
}
回答by Kubba
Got same issue. It happens only if UIButton
's titleLabel
has more than one line. Is it a bug in UIKit?
有同样的问题。只有当UIButton
'stitleLabel
有多于一行时才会发生。这是 UIKit 中的错误吗?
My Swift solution:
我的 Swift 解决方案:
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
}
}
回答by Lord Fresh
I struggled with this for a while and ended up making it work by subclassing UIButton and adding these two functions
我为此苦苦挣扎了一段时间,最终通过继承 UIButton 并添加这两个函数使其工作
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
}
}
回答by Vinay Jain
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
.
您可以做的是创建一个UILabel
并将 a 添加UITapGestureRecognizer
到标签。通过处理点击事件为按钮的操作做任何你想做的事情。并且还要确保您在UILabel
.
This label will now behave as a auto resizing button.
此标签现在将充当自动调整大小按钮。
回答by Xiangdong
What I would suggest is to calculate the width of the text, and calculate the frame by yourself. It's not complicated anyway, get the width of the text first:
我的建议是计算文本的宽度,并自己计算框架。反正也不复杂,先获取文本的宽度:
[NSString sizeWithFont:font];
Do a mod operation and you'll easily find out the number of lines for the text.
做一个 mod 操作,你会很容易地找出文本的行数。
Note this method is for pre iOS7, for iOS 7 and after you might want to try
请注意,此方法适用于 iOS7 之前、iOS 7 以及之后您可能想尝试
[NSString sizeWithAttributes:aDictionary];
回答by Aamir
[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.
[self.button sizeToFit] 如果您的 Autolayout 关闭,应该可以工作。如果您必须使用自动布局,那么其他建议(计算线宽)等更合适。
回答by BSevo
I had the same problem with UIButton
with multilined text, and it also had an image. I used sizeThatFits:
to calculate the size but it calculated wrong height.
我对UIButton
多行文本有同样的问题,它也有一个图像。我曾经sizeThatFits:
计算过尺寸,但它计算出错误的高度。
I did not make it UIButtonTypeCustom
, instead of that I called sizeThatFits:
on button's titleLabel
with size with smaller width (due to image in button):
我没有成功UIButtonTypeCustom
,而是我调用sizeThatFits:
了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;
And then I used height from that size to set button's frame correctly, and it WORKED :)
然后我使用该尺寸的高度来正确设置按钮的框架,它起作用了:)
Maybe they have some bug in internal sizing of UIButton
.
也许他们在UIButton
.
回答by Maria
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
这是 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)
}
回答by Bhavesh Patel
Override the -(CGSize)intrinsicContentSize in Custom UIButton as given below.
如下所示覆盖自定义 UIButton 中的 -(CGSize)intrinsicContentSize。
Objective - C:
目标-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
}
}