Как добавить многострочный текст в UIButton?

У меня есть следующий код...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

... идея состоит в том, что у меня может быть многострочный текст для кнопки, но текст всегда затенен backgroundImage UIButton. Вызов журнала, чтобы показать подпункты кнопки, показывает, что UILabel добавлен, но сам текст не отображается. Является ли это ошибкой в ​​UIButton, или я делаю что-то неправильно?

Ответ 1

Для iOS 6 и выше используйте следующее, чтобы разрешить несколько строк:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to 
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

Для iOS 5 и ниже используйте следующее, чтобы разрешить несколько строк:

button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

2017, для iOS9 вперед,

как правило, просто сделайте эти две вещи:

  1. выберите "Приписанный текст"
  2. во всплывающем окне "Разрыв строки" выберите "Перенос слов"

Ответ 2

Выбранный ответ правильный, но если вы предпочитаете делать такие вещи в Interface Builder, вы можете сделать это:

pic

Ответ 3

Если вы хотите добавить кнопку с заголовком с несколькими строками, задайте настройки интерфейса для кнопки:

[here]

Ответ 4

Для IOS 6:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;

As

UILineBreakModeWordWrap and UITextAlignmentCenter

устарели в IOS 6 и далее.

Ответ 5

Чтобы повторить предложение Роджера Нолана, но с явным кодом, это общее решение:

button.titleLabel?.numberOfLines = 0

Ответ 6

SWIFT 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

Ответ 7

Существует гораздо более простой способ:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Изменить для iOS 3 и более поздних версий:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

Ответ 8

Выровнять по левому краю на iOS7 с автоопределением:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

Ответ 9

В Xcode 9.3 вы можете сделать это с помощью раскадровки, как показано ниже,

enter image description here

Вам нужно установить заголовок кнопки textAlignment по центру

button.titleLabel?.textAlignment =.center

Вам не нужно устанавливать текст заголовка с новой строкой (\n), как показано ниже,

button.setTitle("Good\nAnswer",for:.normal)

Просто установите заголовок,

button.setTitle("Good Answer",for:.normal)

Вот результат,

enter image description here

Ответ 10

Прежде всего, вы должны знать, что UIButton уже имеет UILabel внутри него. Вы можете установить его с помощью –setTitle:forState:.

Проблема с вашим примером заключается в том, что вам нужно установить свойство UILabel numberOfLines в значение, отличное от его значения по умолчанию 1. Вы также должны просмотреть свойство lineBreakMode.

Ответ 11

Для тех, кто использует раскадровку Xcode 4, вы можете щелкнуть по кнопке, а на правой панели "Утилиты" в "Инспекторе атрибутов" вы увидите опцию "Разрыв строки". Выберите Word Wrap, и вам должно быть хорошо идти.

Ответ 12

Ответы здесь расскажут вам, как добиться многострочного названия кнопок программным способом.

Я просто хотел добавить, что если вы используете раскадровки, вы можете ввести [Ctrl + Enter], чтобы заставить новую строку в поле названия кнопки.

НТН

Ответ 13

Вы должны добавить этот код:

buttonLabel.titleLabel.numberOfLines = 0;

Ответ 14

Что касается идеи Брента о том, чтобы присвоить название UILabel как вид сестры, мне это не кажется очень хорошей идеей. Я продолжаю думать о проблемах взаимодействия с UILabel из-за того, что его события касания не проходят через представление UIButton.

С другой стороны, с UILabel в качестве подсмотра UIButton, я довольно удобен, зная, что события касания всегда будут распространяться на супервизор UILabel.

Я использовал этот подход и не заметил никаких проблем, связанных с backgroundImage. Я добавил этот код в -titleRectForContentRect: подкласса UIButton, но этот код также можно поместить в процедуру рисования супервизора UIButton, который в этом случае заменит все ссылки на себя с помощью переменной UIButton.

#define TITLE_LABEL_TAG 1234

- (CGRect)titleRectForContentRect:(CGRect)rect
{   
    // define the desired title inset margins based on the whole rect and its padding
    UIEdgeInsets padding = [self titleEdgeInsets];
    CGRect titleRect = CGRectMake(rect.origin.x    + padding.left, 
                                  rect.origin.x    + padding.top, 
                                  rect.size.width  - (padding.right + padding.left), 
                                  rect.size.height - (padding.bottom + padding].top));

    // save the current title view appearance
    NSString *title = [self currentTitle];
    UIColor  *titleColor = [self currentTitleColor];
    UIColor  *titleShadowColor = [self currentTitleShadowColor];

    // we only want to add our custom label once; only 1st pass shall return nil
    UILabel  *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];


    if (!titleLabel) 
    {
        // no custom label found (1st pass), we will be creating & adding it as subview
        titleLabel = [[UILabel alloc] initWithFrame:titleRect];
        [titleLabel setTag:TITLE_LABEL_TAG];

        // make it multi-line
        [titleLabel setNumberOfLines:0];
        [titleLabel setLineBreakMode:UILineBreakModeWordWrap];

        // title appearance setup; be at will to modify
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        [titleLabel setFont:[self font]];
        [titleLabel setShadowOffset:CGSizeMake(0, 1)];
        [titleLabel setTextAlignment:UITextAlignmentCenter];

        [self addSubview:titleLabel];
        [titleLabel release];
    }

    // finally, put our label in original title view state
    [titleLabel setText:title];
    [titleLabel setTextColor:titleColor];
    [titleLabel setShadowColor:titleShadowColor];

    // and return empty rect so that the original title view is hidden
    return CGRectZero;
}

Я потратил время и написал немного больше об этом здесь. Там я также указываю на более короткое решение, хотя оно не совсем подходит ко всем сценариям и связано с хакингом отдельных частных просмотров. Также там вы можете скачать подклассы UIButton, готовые к использованию.

Ответ 15

Если вы используете автоматическую компоновку на iOS 6, вам также может потребоваться установить свойство preferredMaxLayoutWidth:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

Ответ 16

Установка lineBreakMode в NSLineBreakByWordWrapping (либо в IB, либо в коде) делает метку кнопки многострочной, но не влияет на рамку кнопки.

Если кнопка имеет динамический заголовок, есть один трюк: поместите скрытую UILabel с тем же шрифтом и привяжите ее высоту к высоте кнопки с макетом; когда заданный текст на кнопку и ярлык, а автозапуск сделает всю работу.

Примечание

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

Ответ 17

У меня была проблема с автоматическим макетом, после включения многострочного результата результат был следующим:
enter image description here
поэтому размер titleLabel не влияет на размер кнопки
Я добавил Constraints на основе contentEdgeInsets (в данном случае contentEdgeInsets был (10, 10, 10, 10)
после вызова makeMultiLineSupport():
enter image description here
надеюсь, что это поможет вам (Swift 5.0):

extension UIButton {

    func makeMultiLineSupport() {
        guard let titleLabel = titleLabel else {
            return
        }
        titleLabel.numberOfLines = 0
        titleLabel.setContentHuggingPriority(.required, for: .vertical)
        titleLabel.setContentHuggingPriority(.required, for: .horizontal)
        addConstraints([
            .init(item: titleLabel,
                  attribute: .top,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .top,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.top),
            .init(item: titleLabel,
                  attribute: .bottom,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .bottom,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.bottom),
            .init(item: titleLabel,
                  attribute: .left,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .left,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.left),
            .init(item: titleLabel,
                  attribute: .right,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .right,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.right)
            ])
    }

}

Ответ 18

Он отлично работает.

Добавьте для использования с конфигурационным файлом, таким как Plist, вам нужно использовать CDATA для записи многострочного заголовка, например:

<string><![CDATA[Line1
Line2]]></string>

Ответ 19

Если вы используете автоматическую компоновку.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

Ответ 20

Swift 4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

Ответ 21

В наши дни, если вам действительно нужно, чтобы такие вещи были доступны в конструкторе интерфейсов в каждом конкретном случае, вы можете сделать это с помощью простого расширения, такого как:

extension UIButton {
    @IBInspectable var numberOfLines: Int {
        get { return titleLabel?.numberOfLines ?? 1 }
        set { titleLabel?.numberOfLines = newValue }
    }
}

Затем вы можете просто установить numberOfLines в качестве атрибута для любого подкласса UIButton или UIButton, как если бы это была метка. То же самое относится ко всему множеству других обычно недоступных значений, таких как угловой радиус слоя вида или атрибуты отбрасываемой тени.

Ответ 22

В Swift 5.0 и Xcode 10.2

//UIButton extension
extension UIButton {
     //UIButton properties
     func btnMultipleLines() {
         titleLabel?.numberOfLines = 0
         titleLabel?.lineBreakMode = .byWordWrapping
         titleLabel?.textAlignment = .center        
     }
}

В вашем ViewController звоните вот так

button.btnMultipleLines()//This is your button

Ответ 23

Создайте собственный класс кнопок. Это, безусловно, лучшее решение в долгосрочной перспективе. UIButton и другие классы UIKit очень ограничивают то, как вы можете их настроить.

Ответ 24

self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)

Ответ 25

Я включил ответ jessecurry в STAButton, который является частью моей библиотеки с открытым исходным кодом STAControls. В настоящее время я использую его в одном из приложений, которые разрабатываю, и он работает для моих нужд. Не стесняйтесь открывать вопросы о том, как его улучшить или присылать мне запросы на извлечение.

Ответ 26

Несмотря на то, что вы можете добавить подчиненный элемент в элемент управления, нет никакой гарантии, что он действительно сработает, потому что элемент управления может не ожидать, что он будет там, и, следовательно, может плохо себя вести. Если вы можете уйти от него, просто добавьте ярлык в виде представления для сестры и установите его рамку так, чтобы она перекрывала кнопку; до тех пор, пока он будет отображаться поверх кнопки, ничего, что может сделать кнопка, не скроет его.

Другими словами:

[button.superview addSubview:myLabel];
myLabel.center = button.center;