Подтвердить что ты не робот

IOS: изменение размера UIButton в соответствии с длиной текста

В построителе интерфейса удерживание 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];
4b9b3361

Ответ 1

В Xcode 4.5 и выше это теперь может быть сделано с помощью ' Auto-layout/Constraints '.

Основными преимуществами являются:

  1. Вам вообще не нужно программно устанавливать кадры!
  2. Если все сделано правильно, вам не нужно беспокоиться о сбросе кадров для изменения ориентации.
  3. Кроме того, изменения устройства не должны беспокоить вас (читайте, не нужно кодировать отдельно для разных размеров экрана).

Несколько недостатков:

  1. Не поддерживает обратную совместимость - работает только для iOS 6 и выше.
  2. Нужно ознакомиться (но сэкономит время позже).

Самое классное, что мы можем сосредоточиться на объявлении намерения, такого как:

  • Я хочу, чтобы эти две кнопки были одинаковой ширины; или же
  • Мне нужно, чтобы этот вид был вертикально центрирован и простирался до максимума в 10 пунктов от края суперпредставления; или даже,
  • Я хочу, чтобы размер этой кнопки/ярлыка изменялся в соответствии с отображаемым ярлыком!

Вот простой учебник, чтобы познакомиться с автоматическим макетом.

Для более подробной информации.

Сначала это занимает некоторое время, но, похоже, оно того стоит.

Ответ 2

В 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, но вы начнете с правильного места.

Ответ 3

Способ сделать это в коде:

[button sizeToFit];

Если вы являетесь подклассом и хотите добавить дополнительные правила, вы можете переопределить:

- (CGSize)sizeThatFits:(CGSize)size;

Ответ 4

Если ваша кнопка была сделана с помощью Interface Builder и вы меняете заголовок в коде, вы можете сделать это:

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

Ответ 5

Swift:

Важная вещь здесь , когда вы вызовете .sizeToFit(), это должно быть после установки отображаемого текста, чтобы он мог читать необходимый размер, если позже вы обновите текст, а затем вызовите его еще раз.

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

Ответ 6

Чтобы сделать это с помощью autolayout, попробуйте установить ограничение переменной ширины:

Width Constraint

Вам также может понадобиться настроить Content Hugging Priority Content Compression Resistance Priority чтобы получить нужные вам результаты.


UILabel полностью автоматически измеряет себя:

Эта UILabel просто устанавливается по центру на экране (только два ограничения, горизонтальное/вертикальное):

Изменяет ширину полностью автоматически:

Вам не нужно устанавливать любую ширину или высоту - это полностью автоматический.

enter image description here

enter image description here

Обратите внимание, что маленькие желтые квадраты просто прикреплены ("интервал" от нуля). Они автоматически перемещаются при изменении размера UILabel.

Добавление ограничения "> =" устанавливает минимальную ширину для UILabel:

enter image description here

Ответ 7

Если вы хотите изменить размер текста в отличие от кнопки, вы можете использовать...

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;

Ответ 8

sizeToFit не работает правильно. вместо:

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

Вы также можете добавить contentInset к кнопке:

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

Ответ 9

Просто:

  • Создайте UIView в качестве обертки с автоматической компоновкой для просмотра.
  • Поместите UILabel внутри этой оболочки. Добавьте ограничения, которые будут прикреплять ярлык tyour к краям обертки.
  • Поместите UIButton внутри вашей оболочки, затем просто добавьте те же ограничения, что и для UILabel.
  • Наслаждайтесь автоматической кнопкой вместе с текстом.

Ответ 10

У меня есть дополнительные потребности, связанные с этим сообщением, что 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 location of button
    boundsForText.origin.x += (boundsForText.size.width - stringSize.width) / 2;
    boundsForText.size.width = stringSize.width;
    [button setFrame:boundsForText];
 }

Ответ 11

Этот класс кнопок с автоматическим изменением размера текста (для 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);
         }
     }
}

Ответ 12

Swift 4.2

Слава богу, это решено. После установки текста для кнопки, вы можете извлечь intrinsicContentSize, который является естественным размером из UIView (официальный документ здесь). Для UIButton вы можете использовать его, как показано ниже.

button.intrinsicContentSize.width

Для вашей информации я отрегулировал ширину, чтобы она выглядела правильно.

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

имитатор

UIB-кнопки с intrinsicContentSize

Источник: https://riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font