在界面生成器中,按住 Command + = 将调整按钮的大小以适合其文本。我想知道在将按钮添加到视图之前是否可以通过编程方式执行此操作。
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button.titleLabel setFont:[UIFont fontWithName:@"Arial-BoldMT" size:12]];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
// I need to know the width needed to accomodate NSStringVariable
[button setTitle:NSStringVariable forState:UIControlStateNormal];
// So that I can set the width property of the button before addSubview
[button setFrame:CGRectMake(10, 0, width, fixedHeight)];
[subNavigation addSubview:button];
在 UIKit 中,添加了 NSString 类以从给定的 NSString 对象获取以某种字体呈现时它将占用的大小。
简而言之,如果你去:
CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]];
//or whatever font you're using
[button setFrame:CGRectMake(10,0,stringsize.width, stringsize.height)];
...您将按钮的框架设置为您正在呈现的字符串的高度和宽度。
您可能希望在该 CGSize 周围试验一些缓冲区空间,但您将从正确的地方开始。
在代码中执行此操作的方法是:
[button sizeToFit];
如果您是子类化并想要添加额外的规则,您可以覆盖:
- (CGSize)sizeThatFits:(CGSize)size;
-(CGSize)sizeThatFits:(CGSize)size
。
[button setTitle:@"Your text here" forState:UIControlStateNormal];
[button sizeToFit];
此外,如果您稍后更新文本,请不要忘记再次调用它。
sizeToFit()
不尊重标题边缘插图。
如果您的按钮是使用 Interface Builder 制作的,并且您正在更改代码中的标题,则可以执行以下操作:
[self.button setTitle:@"Button Title" forState:UIControlStateNormal];
[self.button sizeToFit];
迅速:
这里重要的是 什么时候 你会调用 .sizeToFit()
,它应该在设置要显示的文本之后才能读取所需的大小,如果你稍后更新文本,然后再次调用它。
var button = UIButton()
button.setTitle("Length of this text determines size", forState: UIControlState.Normal)
button.sizeToFit()
self.view.addSubview(button)
要使用自动布局完成此操作,请尝试设置可变宽度约束:
https://i.stack.imgur.com/iM1Vk.png
您可能还需要调整 Content Hugging Priority
和 Content Compression Resistance Priority
以获得所需的结果。
UILabel 完全自动调整大小:
这个 UILabel 被简单地设置为在屏幕上居中(只有两个约束,水平/垂直):
它完全自动改变宽度:
您不需要设置任何宽度或高度 - 它是完全自动的。
https://i.stack.imgur.com/Us3b2.png
https://i.stack.imgur.com/pVfMC.png
请注意,黄色小方块只是简单地附加(“间距”为零)。它们会随着 UILabel 调整大小而自动移动。
添加 ">=" 约束设置 UILabel 的最小宽度:
https://i.stack.imgur.com/raRNQ.png
如果要调整文本而不是按钮的大小,可以使用...
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.minimumScaleFactor = .5;
// The .5 value means that I will let it go down to half the original font size
// before the texts gets truncated
// note, if using anything pre ios6, you would use I think
button.titleLabel.minimumFontSize = 8;
sizeToFit 无法正常工作。反而:
myButton.size = myButton.sizeThatFits(CGSize.zero)
您还可以将 contentInset
添加到按钮:
myButton.contentEdgeInsets = UIEdgeInsetsMake(8, 8, 4, 8)
斯威夫特 4.2
感谢上帝,这解决了。为按钮设置文本后,您可以从 UIView 中检索作为自然大小的intrinsicContentSize(官方文档为here)。对于 UIButton,您可以像下面这样使用它。
button.intrinsicContentSize.width
为了您的信息,我调整了宽度以使其看起来正确。
button.frame = CGRect(fx: xOffset, y: 0.0, width: button.intrinsicContentSize.width + 18, height: 40)
模拟器
UIButtons with intrinsicContentSize
来源:https://riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font
简单地:
创建 UIView 作为具有自动布局的包装器到周围的视图。将 UILabel 放入该包装器中。添加将标签粘贴到包装边缘的约束。将 UIButton 放入包装器中,然后简单地添加与 UILabel 相同的约束。享受自动调整大小的按钮和文本。
出于某种原因,func sizeToFit()
对我不起作用。我的设置是我在 UITableViewCell
中使用一个按钮,并且我正在使用自动布局。
对我有用的是:
获取宽度约束获取intrinsicContentSize 宽度,因为根据此文档自动布局不知道intrinsicContentSize。将宽度约束设置为 intrinsicContentSize 宽度
https://i.stack.imgur.com/IoblM.png
https://i.stack.imgur.com/Jo445.png
https://i.stack.imgur.com/D8UKk.png
我有一些与这篇文章相关的额外需求,sizeToFit
无法解决。无论文本如何,我都需要将按钮保持在其原始位置的中心。我也不希望按钮大于其原始大小。
因此,我将按钮布局为其最大尺寸,将该尺寸保存在控制器中,并在文本更改时使用以下方法来调整按钮的大小:
+ (void) sizeButtonToText:(UIButton *)button availableSize:(CGSize)availableSize padding:(UIEdgeInsets)padding {
CGRect boundsForText = button.frame;
// Measures string
CGSize stringSize = [button.titleLabel.text sizeWithFont:button.titleLabel.font];
stringSize.width = MIN(stringSize.width + padding.left + padding.right, availableSize.width);
// Center's location of button
boundsForText.origin.x += (boundsForText.size.width - stringSize.width) / 2;
boundsForText.size.width = stringSize.width;
[button setFrame:boundsForText];
}
此按钮类具有文本高度自动调整大小(适用于 Xamarin,但可以重写为其他语言)
[Register(nameof(ResizableButton))]
public class ResizableButton : UIButton
{
NSLayoutConstraint _heightConstraint;
public bool NeedsUpdateHeightConstraint { get; private set; } = true;
public ResizableButton(){}
public ResizableButton(UIButtonType type) : base(type){}
public ResizableButton(NSCoder coder) : base(coder){}
public ResizableButton(CGRect frame) : base(frame){}
protected ResizableButton(NSObjectFlag t) : base(t){}
protected internal ResizableButton(IntPtr handle) : base(handle){}
public override void LayoutSubviews()
{
base.LayoutSubviews();
UpdateHeightConstraint();
InvalidateIntrinsicContentSize();
}
public override void SetTitle(string title, UIControlState forState)
{
NeedsUpdateHeightConstraint = true;
base.SetTitle(title, forState);
}
private void UpdateHeightConstraint()
{
if (!NeedsUpdateHeightConstraint)
return;
NeedsUpdateHeightConstraint = false;
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
var rect = new CGRect(Frame.X, Frame.Y, Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
if (_heightConstraint != null)
RemoveConstraint(_heightConstraint);
_heightConstraint = NSLayoutConstraint.Create(this, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1, rect.Height);
AddConstraint(_heightConstraint);
}
public override CGSize IntrinsicContentSize
{
get
{
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
return new CGSize(Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
}
}
}
老实说,我认为情节提要中没有简单的复选框来表示您想要调整按钮大小以适应文本,这真的很可惜。嗯……随便。
这是使用故事板的最简单的解决方案。
放置 UIView 并为其设置约束。示例:将 UILabel 放在 UIView 中。设置约束以将其附加到 UIView 的边缘。将您的 UIButton 放在 UIView 中。设置相同的约束以将其附加到 UIView 的边缘。将 UILabel 的行数设置为 0。设置网点。
@IBOutlet var button: UIButton!
@IBOutlet var textOnTheButton: UILabel!
得到一些很长很长的标题。
let someTitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
在 viewDidLoad 上为 UILabel 和 UIButton 设置标题。
override func viewDidLoad() {
super.viewDidLoad()
textOnTheButton.text = someTitle
button.setTitle(someTitle, for: .normal)
button.titleLabel?.numberOfLines = 0
}
运行它以确保按钮已调整大小并且可以按下。
https://i.stack.imgur.com/9qjfz.png
因为 sizeToFit
将忽略 titleEdgeInsets
设置。在我的例子中,按钮标题是固定文本,所以我使用自动布局给每个按钮一个宽度约束。
而且我认为如果是动态文本长度,您需要先获取字符串大小并更新 viewDidLayoutSubview
中的按钮约束。
lazy var importButton: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("Import", for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 18, weight: .bold)
btn.setTitleColor(.white, for: .normal)
btn.titleEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
btn.backgroundColor = .myBlue
btn.layer.cornerRadius = 8
btn.clipsToBounds = true
btn.addTarget(self, action: #selector(importButtonTapped), for: .touchUpInside)
return btn
}()
lazy var stitchButton: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("Stitch", for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 18, weight: .bold)
btn.setTitleColor(.white, for: .normal)
btn.titleEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
btn.backgroundColor = .myGreen
btn.layer.cornerRadius = 8
btn.clipsToBounds = true
btn.addTarget(self, action: #selector(stitchButtonTapped), for: .touchUpInside)
return btn
}()
func setViews() {
title = "Image Stitcher"
view.backgroundColor = .systemBackground
view.addSubview(importButton)
view.addSubview(stitchButton)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
NSLayoutConstraint(item: importButton, attribute: .centerX, relatedBy: .equal, toItem: g, attribute: .trailing, multiplier: 0.3, constant: 0),
importButton.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -50),
importButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.25),
importButton.heightAnchor.constraint(equalTo: importButton.widthAnchor, multiplier: 0.5),
NSLayoutConstraint(item: stitchButton, attribute: .centerX, relatedBy: .equal, toItem: g, attribute: .trailing, multiplier: 0.7, constant: 0),
stitchButton.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -50),
stitchButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.25),
stitchButton.heightAnchor.constraint(equalTo: stitchButton.widthAnchor, multiplier: 0.5),
])
}
https://i.stack.imgur.com/AJfza.jpg
在 Xcode 4.5 及更高版本中,现在可以使用“自动布局/约束”来完成。
主要优点是:
您根本不需要以编程方式设置框架!如果操作正确,您无需为改变方向而重新设置框架。此外,设备更改不必打扰您(阅读,无需为不同的屏幕尺寸单独编码)。
几个缺点:
不向后兼容 - 仅适用于 iOS 6 及更高版本。需要熟悉(但以后会节省时间)。
最酷的事情是我们可以专注于声明一个意图,例如:
我希望这两个按钮的宽度相同;或者
我需要这个视图垂直居中并从超级视图的边缘扩展到最大 10 pts;甚至,
我希望这个按钮/标签根据它显示的标签调整大小!
Here 是介绍自动布局的简单教程。
对于 more details。
一开始需要一些时间,但看起来确实值得付出努力。