iOS:UIButton根据文本长度调整大小


134

在界面生成器中,按住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];

1
请注意这个非常老的问题:如今(2017年),只需将约束设置为“大于或等于”即可。(Tad发出的以下通知答复)
Fattie

@Fattie“ 大于或等于 ”约束不足以与AutoLayout兼容。如今(2017+)你要么换按钮内在的东西,调整大小正常(巴特洛梅耶Semańczyk答案),或者应该继承的UIButton的,如stackoverflow.com/a/50575588/1033581
心教堂

嗨@Cœur-自动版式有很多细微之处。您可能正在考虑稍微不同的情况?但是,幸运的是,您完全错了- 试试吧!只需将UIButton放在视图控制器上。显然设置了水平和垂直中心。然后添加> = 100宽度约束。它在最新的iOS中完美运行。
Fattie

1
(对于任何刚接触自动布局的人,这里...........只需TBC根本就不需要添加任何东西,并且UIButton(还有UILabel等)将随着文本更改自动调整为宽度。限制适当的H / V位置。)
Fattie,

@法蒂示范。特别是,在运行时,它的行为像:github.com/Coeur/autolayoutButton/blob/master/buttonSelfSizing/...
心教堂

Answers:


1

在Xcode 4.5及更高版本中,现在可以使用“ 自动布局/约束 ” 来完成此操作。

主要优点是:

  1. 您根本不需要以编程方式设置框架!
  2. 如果操作正确,则无需为重新设置方向而烦恼。
  3. 此外,设备更改也不必打扰您(阅读,无需针对不同的屏幕尺寸单独编码)。

缺点:

  1. 不向后兼容-仅适用于iOS 6及更高版本。
  2. 需要熟悉(但以后可以节省时间)。

最酷的事情是我们将重点放在声明意图上,例如:

  • 我希望这两个按钮的宽度相同。要么
  • 我需要使该视图垂直居中,并从超级视图的边缘延伸到最大10 pt。甚至,
  • 我希望此按钮/标签根据其显示的标签调整大小!

是一个介绍自动布局的简单教程。

有关更多详细信息

起初需要一些时间,但是可以肯定,这是值得的。


3
我差点错过了这个答案-它确实需要更多的赞成票。使用此解决方案,可以避免嵌入字体的面孔名称和大小或仅适用于iOS 7的调用。我只是简单地设置了我希望UIButton扩展的那一侧的约束,仅此而已。
卡尔2014年

/:几乎完美的解决方案,遗憾的是它不一样,如果使用titleEdgeInsets工作
佐尔坦

130
这是一个很差的答案-它详细说明了AutoLayout本身的优点,而不是在这种情况下如何应用AutoLayout来解决提问者的问题。
mattsven 2015年

4
我想知道答案是否有可能以编程方式做到 ……
Juan Boero

@JuanPabloBoeroAlvarez可以在“界面生成器”中和/或以编程方式指定“自动布局”约束。
Slipp D. Thompson

130

在UIKit中,NSString类有一些附加功能,可从给定的NSString对象获得以某种字体呈现时它将占用的大小。

Docs在这里。现在,这里已过时之下。

简而言之,如果您去:

CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]]; 
//or whatever font you're using
[button setFrame:CGRectMake(10,0,stringsize.width, stringsize.height)];

...您已经将按钮的框架设置为要渲染的字符串的高度和宽度。

您可能要尝试在CGSize周围使用一些缓冲区空间,但是您将从正确的位置开始。


4
看起来iOS默认填充为12px,8px。
Ben Lachman 2012年

19
在iOS 7.0中不推荐使用sizeWithFont。使用sizeWithAttributes:相反
carmen_munich 2013年

6
我强烈建议不要再使用框架,而只能使用约束。
吉尔·桑德

@GilSand有没有办法为此使用接口生成器?
huggie

是的,谷歌搜索应该会给您很多有用的结果
Gil Sand

101

在代码中执行此操作的方法是:

[button sizeToFit];

如果您是子类化并想要添加其他规则,则可以覆盖:

- (CGSize)sizeThatFits:(CGSize)size;

5
sizeToFit在UIButton或UILabel之类的标准控件上完美工作。如果要在自定义UIView上进行操作,则需要实现-(CGSize)sizeThatFits:(CGSize)size
卡梅隆·洛厄尔·帕尔默

4
仅当在设置文本后放上它时才起作用,否则,关于它应该多大的信息就不多了: [button setTitle:@"Your text here" forState:UIControlStateNormal]; [button sizeToFit]; 另外,如果以后更新文本,请不要忘记再次调用它。
Juan Boero

确保仅以这种方式设置文本:[myButton setTitle:@“ my title” forState:UIControlStateNormal]; 对我而言,直到我重复该声明,它才起作用。
Darius Miliauskas,

7
sizeToFit()不尊重标题边缘插图。
凯琳

32

如果您的按钮是使用Interface Builder创建的,并且您要更改代码中的标题,则可以执行以下操作:

[self.button setTitle:@"Button Title" forState:UIControlStateNormal];
[self.button sizeToFit];

1
即使您的按钮是用代码制作的,也可以做到这一点。
Markus

22

迅速:

这里重要的是何时调用.sizeToFit(),应该在将文本设置为显示之后才能读取,以便可以读取所需的大小,如果以后更新文本,则再次调用它。

var button = UIButton()
button.setTitle("Length of this text determines size", forState: UIControlState.Normal)
button.sizeToFit()
self.view.addSubview(button)

18

要使用自动布局完成此操作,请尝试设置可变宽度约束:

宽度限制

您可能还需要调整Content Hugging PriorityContent Compression Resistance Priority获得所需的结果。


UILabel 完全自动调整大小

只需将UILabel设置为在屏幕上居中即可(仅两个约束,水平/垂直):

它完全自动改变宽度:

您无需设置任何宽度或高度-这是全自动的。

在此处输入图片说明

在此处输入图片说明

请注意,黄色小方块被简单地附加了(“间距”为零)。它们随着UILabel调整大小而自动移动。

添加“> =”约束可设置UILabel的最小宽度:

在此处输入图片说明


16

如果要调整文本大小而不是按钮大小,可以使用...

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;

3
* AdjustsFontSizeToFitWidth
Daniel Bang

8

sizeToFit无法正常工作。代替:

myButton.size = myButton.sizeThatFits(CGSize.zero)

您还可以添加contentInset到按钮:

myButton.contentEdgeInsets = UIEdgeInsetsMake(8, 8, 4, 8)


来自苹果公司的有关sizeToFit的文档://调用sizeThatFits:具有当前视图范围并更改范围大小。因此它可以正常工作,您只需要在设置文本之后进行设置即可。
Markus

5

只是:

  1. UIView使用自动布局创建包装器以查看周围的视图。
  2. 放在UILabel那个包装纸里面。添加约束,将您的标签粘贴到包装纸的边缘。
  3. 放入UIButton包装器中,然后简单地添加与相同的约束UILabel
  4. 享受自动调整大小的按钮以及文字的乐趣。

1
辅助功能是否很好玩?
jasonszhao

4

斯威夫特4.2

谢谢上帝,这解决了。在按钮上设置文本之后,您可以从UIView检索nativeContentSize,它是自然大小(官方文档在这里)。对于UIButton,您可以如下使用它。

button.intrinsicContentSize.width

供您参考,我调整了宽度以使其看起来正确。

button.frame = CGRect(fx: xOffset, y: 0.0, width: button.intrinsicContentSize.width + 18, height: 40)

仿真器

具有internalContentSize的UIButton

来源:https//riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font


1
您能否再提供一些背景信息?您的代码行与问题中的代码有何关系?您还可以总结一下您建议的代码做什么吗?仅提供链接作为说明不是该网站的正确格式(出于某些原因,请参阅meta.stackexchange.com/a/8259/266197),但是如果您添加一些说明和上下文,您的答案将变得更有价值!
NOhs

3

我有一些与此帖子相关的其他需求sizeToFit无法解决。无论文本如何,我都需要将按钮居中放置在其原始位置。我也从来不希望按钮大于其原始大小。

因此,我将按钮设置为最大大小,将该大小保存在Controller中,并在文本更改时使用以下方法来调整按钮的大小:

+ (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];
 }

1

具有高度自动调整大小的文本的此类按钮(对于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);
         }
     }
}

1

由于某种原因,func sizeToFit()对我不起作用。我的设置是使用a内的按钮,UITableViewCell并使用自动布局。

对我有用的是:

  1. 得到宽度约束
  2. 获取intrinsicContentSize宽度,因为根据此文档,自动布局不了解intrinsicContentSize。将宽度约束设置为intrinsicContentSize宽度

在此处输入图片说明

这是来自的两个标题 Debug View Hierachry 在此处输入图片说明

在此处输入图片说明


0

老实说,我认为在情节提要中没有简单的复选框来表明您要调整按钮的大小以容纳文本真是可耻。好吧...随便

这是使用情节提要的最简单解决方案。

  1. 放置UIView并为其施加约束。例: 在此处输入图片说明
  2. 将UILabel放在UIView中。设置约束以将其附加到UIView的边缘。

  3. 将您的UIButton放在UIView中。设置相同的约束以将其附加到UIView的边缘。

  4. UILabel的行数设置为0。 在此处输入图片说明

  5. 设置网点。

    @IBOutlet var button: UIButton!
    @IBOutlet var textOnTheButton: UILabel!
  1. 获得一些长而长的标题。

    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."
  1. 在viewDidLoad上,设置UILabel和UIButton的标题。

    override func viewDidLoad() {
        super.viewDidLoad()
        textOnTheButton.text = someTitle
        button.setTitle(someTitle, for: .normal)
        button.titleLabel?.numberOfLines = 0
    }
  1. 运行它以确保调整了按钮的大小并可以将其按下。

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.