Як додати багаторядковий текст до UIButton?


368

У мене є такий код ...

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

... ідея полягає в тому, що я можу мати багаторядковий текст для кнопки, але текст завжди затемнений фоном зображення UIButton. Виклик журналу для відображення підвідних кнопок показує, що UILabel доданий, але сам текст не може бути видно. Це помилка в UIButton чи я щось роблю не так?


7
button.titleLabel?.numberOfLines = 0
ma11hew28

2
Зверніть увагу на цей дуже старий QA, в сучасному Xcode ДУЖЕ ПРОСТО, ОБИРАЙТЕ "ДОПОМОГАНИЙ ТЕКСТ", і тоді це банально, виберіть "обгортку символів".
Fattie

Також дивіться оновлену відповідь на подібне запитання.
ToolmakerSteve

дивіться цю відповідь (кілька рядків, ширина розміщення, висота підгонки) для тексту кнопки stackoverflow.com/a/59211399/7523163
Хамід Реза Ансарі

Відповіді:


676

Для 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. у спливаючому вікні "Розрив рядка" виберіть "Обертання слів"

5
Зверніть увагу, що ці завдання застаріли в iOS 6. Дивіться відповідь нижче від @NiKKi щодо оновленого синтаксису.
Аарон Брагер

6
Просто люди знають: це не працює, якщо ви використовуєте NSAttributedString
Чувак

29
Власне, просто додайте button.titleLabel.numberOfLines = 0; Це зробить рядки необмеженими. І button.titleLabel.textAlignment = NSTextAlignmentLeft; якщо ви хочете залишити виправданий текст, оскільки заголовок за замовчуванням зосереджений.
RyJ

4
Швидкоbutton.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
Роберт

1
Дякуємо @Robert за швидке рішення. Можна також використовувати висновок і опускати NSLineBreakMode, так як: button.titleLabel?.lineBreakMode = .ByWordWrapping.
mjswensen

145

Обрана відповідь правильна, але якщо ви віддаєте перевагу робити подібні речі в Interface Builder, ви можете зробити це:

рис


58
Дякую моєму 24-річному «я», що написав цю відповідь, від 28-річного «я».
Адам Уейт

5
І залишитися з єдиним Interface Builder установки, слід встановити titleLabel.textAlignmentз Numberзначенням , щоб 1в , User Defined Runtime Attributedщоб зробити текст по центру
AnthoPak

2
Дякую вашій 28-річній власній власності від моєї 24-річної самості!
Даніель Спрінгер

59

Якщо ви хочете додати кнопку із заголовком, у центрі якого розміщено декілька рядків, встановіть для кнопки налаштування інтерфейсу:

[ тут]


Чи можете ви додати текстовий опис того, як цього досягти. Зображення чудове, але якщо воно стане недоступним, ваша відповідь буде марною.
Рорі Маккросан

1
@RoryMcCrossan Привіт, я додав зображення вище. Ви можете це переглянути? Зверніть увагу, Xcode 7 все ще є помилковою, тому назва кнопки може зникнути. Однак після запуску програми ви отримаєте бажаний результат.
user5440039

2
Насправді це найкраща відповідь у цій темі. Працює негайно і показує текст із ІБ із центром. Дякую!
RainCast

@ user5440039 Дякую за чудову відповідь. Не потрібно додавати текстовий опис.
Fattie

54

Для IOS 6:

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

Як

UILineBreakModeWordWrap and UITextAlignmentCenter

застаріли в IOS 6 і далі.


Всередині не NSText.hв Foundationтам немає DEPRECATED додав. Доступний з 6.0, але не застарілий.
Алекс Ціо

Швидко: button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping button.titleLabel?.textAlignment = NSTextAlignment.Center
jcity

30

Щоб перезапустити пропозицію Роджера Нолана, але з явним кодом, це загальне рішення:

button.titleLabel?.numberOfLines = 0


13

У Xcode 9.3 ви можете це зробити, використовуючи табло, як показано нижче,

введіть тут опис зображення

Вам потрібно встановити текст заголовка textAlignment до центру

button.titleLabel?.textAlignment = .center

Вам не потрібно встановлювати текст заголовка новим рядком (\ n), як показано нижче,

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

Просто встановіть назву,

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

Ось результат,

введіть тут опис зображення


myButton.titleLabel.textAlignment = NSTextAlignmentCenterзаява також потрібна.
tounaobun

11

Є набагато простіший спосіб:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Редагувати для iOS 3 та новіших версій :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

4
UIButton.lineBreakMode застаріло в 3.0, тому це вже не є найкращим варіантом.
Крістофер Пікслі

2
lineBreakMode застаряється лише як пряма властивість UIButton. Нас направлено до "Використовувати натомість властивість lineBreakMode" titleLabel ". Відповідно я відредагував відповідь Валерія. Це все-таки хороший варіант.
Wienke

11

Вирівняйте ліворуч на iOS7 з автоматичним розгортанням:

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

9

У мене виникла проблема з автоматичним компонуванням, після ввімкнення багаторядкових результатів результат був такий: тому розмір не впливає на розмір кнопки, який я додав на основі (у цьому випадку contentEdgeInsets був (10, 10, 10, 10 ) після дзвінка : сподіваюся, що це допоможе вам (швидкий 5.0):
введіть тут опис зображення
titleLabel
ConstraintscontentEdgeInsets
makeMultiLineSupport()
введіть тут опис зображення

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)
            ])
    }

}

Працює ідеально швидко 5. Я також додав свою функцію до центру тексту за допомогою кнопки. func centerTextInButton () {guard let titleLabel = titleLabel else {return} titleLabel.textAlignment = .center}
ShadeToD

Дякую. Це таке хороше рішення.
Ешелон

Я виявив, що додавати обмеження не потрібно, просто встановіть текст після того, як встановлено рядокBreakMode / textAlignment / numberOfLines. А також встановіть titleEdgeInsets для верхнього та нижнього вставки.
Білл Чан

@BillChan, на жаль, працює не у всіх випадках
Амір Хорсанді

7

Перш за все, ви повинні знати, що UIButton вже має UILabel всередині нього. Ви можете встановити його за допомогою –setTitle:forState:.

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


Я знаю властивість заголовка, але, наскільки я можу сказати, неможливо встановити його для використання більш ніж одного рядка, отже, такий підхід. Якщо я відключу backgroundImage, з'явиться мій UILabel, що мені підказує про помилку як у enterSubviewToFront, так і в самому UIButton.
Полювання на Овеїна

4

Для тих, хто використовує рекламну дошку Xcode 4, ви можете натиснути кнопку, а в правій частині панелі утиліти в розділі Атрибути інспектора ви побачите опцію для розриву рядків. Оберіть програму Word Wrap, і вам слід добре піти.


4

Відповіді тут розповідають, як програмно домогтися багаторядкової кнопки.

Я просто хотів додати, що якщо ви використовуєте мовленнєві дошки, ви можете ввести [Ctrl + Enter], щоб примусити новий рядок у полі заголовка кнопки.

HTH



3

Що стосується ідеї Брента про те, щоб поставити назву UILabel як вигляд рідних братів, то мені це не дуже подобається. Я продовжую думати про проблеми взаємодії з UILabel через те, що його події на дотик не потрапляють через погляд UIButton.

З іншого боку, з UILabel як підвидом UIButton, мені дуже зручно, знаючи, що сенсорні події завжди будуть поширюватися на нагляд UILabel.

Я застосував такий підхід і не помітив жодних проблем, про які повідомляв backgroundImage. Я додав цей код у -titleRectForContentRect: підкласу UIButton, але код також може бути розміщений у графіці нагляду UIButton superview, що в такому випадку ви повинні замінити всі посилання на self змінною 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's 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, готовий до використання.


3

Якщо ви використовуєте автоматичну компоновку на iOS 6, можливо, вам також знадобиться встановити preferredMaxLayoutWidthвластивість:

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

3

Встановлення lineBreakMode на NSLineBreakByWordWrapping (або в IB, або в коді) робить мітку кнопки багаторядковою, але не впливає на рамку кнопки.

Якщо кнопка має динамічний заголовок, є одна хитрість: поставте прихований UILabel з таким же шрифтом і прив’яжіть його висоту до висоти кнопки з макетом; коли встановити текст на кнопку, а мітка і авторозкладка зроблять всю роботу.

Примітка

Висота внутрішнього розміру однорядкової кнопки більша, ніж етикетка, тому для запобігання зменшенню висоти етикетки її вертикальним Пріоритет обіймання вмісту повинен бути більшим, ніж вертикальний опір вмісту на стиск вмісту.


3

У 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

2

Це прекрасно працює.

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

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

2

Якщо ви використовуєте автоматичне розташування.

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

2

швидкий 4.0

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

2

У цей час, якщо вам справді потрібна така річ, щоб вона була доступна в програмі інтерфейсів у кожному конкретному випадку, ви можете зробити це з простим розширенням, як це:

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

Тоді ви можете просто встановити numberOfLines як атрибут на будь-якому підкласі UIButton або UIButton так, ніби це мітка. Те саме стосується цілого ряду інших зазвичай недоступних значень, таких як кутовий радіус шару подання або атрибути тіні, яку він кидає.


2

Швидкий 5, для багаторядкового тексту в UIButton

  let button = UIButton()
  button.titleLabel?.lineBreakMode = .byWordWrapping
  button.titleLabel?.textAlignment = .center
  button.titleLabel?.numberOfLines = 0 // for Multi line text

0

Згорніть свій власний клас кнопок. Це, безумовно, найкраще рішення в довгостроковій перспективі. UIButton та інші класи UIKit дуже обмежують їх налаштування.


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

self.btnError.titleLabel?.textAlignment = .center

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

0

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


0

Щоб виправити відстань мітки заголовка до кнопки, встановіть titleEdgeInsets та інші властивості перед setTitle:

    let set = UIButton()
    sut.titleLabel?.lineBreakMode = .byWordWrapping
    sut.titleLabel?.numberOfLines = 0
    sut.titleEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
    sut.setTitle("Dummy button with long long long long long long long long title", for: .normal)

PS Я перевірив налаштування titleLabel? .TextAlignment не потрібен і заголовок вирівнюється .natural.


-4

Хоча добре додавати підпрепарат до елемента керування, немає жодної гарантії, що він дійсно спрацює, оскільки контроль може не очікувати, що він буде там, і, отже, може вести себе погано. Якщо ви можете піти з нею, просто додайте мітку як перегляд кнопки та встановіть її кадр так, щоб він перекривав кнопку; доки він встановлений у верхній частині кнопки, нічого, що може зробити це, не затьмарить його.

Іншими словами:

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

2
Будь ласка, якщо ви пропонуєте такий некрасивий підхід, принаймні не помиляйтесь у прикладі свого коду :). Етикетка не повинна мати такий самий центр, як кнопка, якщо це підвід. Використовуйте myLabel.frame = button.bounds; або myLabel.center = cgPointMake (button.frame.size.with * 0.5, button.frame.size.height * 0.5)
JakubKnejzlik

1
@GrizzlyNetch Я спеціально раджу не додавати його як підвид кнопки. addSubview:тут він додає його до buttonнагляду, тим самим робить його зближенням кнопки, тож відповідність їх центрам правильна.
Brent Royal-Gordon

Ах, моя помилка! Ви маєте рацію, я пропустив "маленький" факт, що це в нагляді: D ... вибачте :)
JakubKnejzlik

Оскільки це не саме запитання, це рішення було б поганим способом реалізації питання, оскільки кнопка елемента має заголовок.
Пабло Бланко

Це була розумна порада в iPhone OS 2.0. Наразі є набагато кращі способи зробити це. : ^)
Brent Royal-Gordon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.