UIButton с двумя строками текста в заголовке (numberOfLines = 2)

86

Я пытаюсь создать объект UIButtonс двумя строками текста в заголовкеLabel. Это код, который я использую:

    UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
    titleButton.titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
    [titleButton setTitle:@"This text is very long and should get truncated at the end of the second line" forState:UIControlStateNormal];
    titleButton.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    titleButton.titleLabel.numberOfLines = 2;
    [self addSubview:titleButton];

Когда я пробую это сделать, текст появляется только в одной строке. Кажется, единственный способ получить более одной строки текста UIButton.titleLabel- это установить numberOfLines=0и использовать UILineBreakModeWordWrap. Но это не гарантирует, что текст будет ровно двумя строками.

Однако использование равнины UILabelдействительно работает:

    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
    titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
    titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
    titleLabel.numberOfLines = 2;
    titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    [self addSubview:titleLabel];

Кто-нибудь знает, как сделать UIButtonработу с двумя строчками? Единственное решение - создать отдельный UILabelтекст для хранения и добавить его в качестве подпредставления кнопки?

маркетолог
источник
1
Вы видели это ? - stackoverflow.com/questions/604632/…
Viraj
Вирадж, да, если установить numberOfLines=0и использовать UILineBreakModeWordWrap, можно получить несколько строк. Проблема в том, что если текст будет слишком длинным, он может дать больше двух строк. Мне нужно ровно два одиночных символа с точками в конце второй строки (если текст слишком длинный).
маркетолог
О, тогда я думаю, что добавление subview может быть единственным выходом.
Viraj

Ответы:

87

Обновленный ответ для более поздних версий iOS

Поскольку это принятый ответ, здесь добавлен ответ @Son:

Установите эти свойства в titleLabel вашей кнопки.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2; // if you want unlimited number of lines put 0

Swift 3 и 4:

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 2 // if you want unlimited number of lines put 0

Оригинальный ответ для более старой версии iOS

Если вы хотите, чтобы наверху были две строки текста, UIButtonвы должны добавить UIlabelповерх них именно это.

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[myButton addSubview:titleLabel]; //add label to button instead.

Обновлено для решения для построения интерфейсов

Добавлен ответ @Borut Tomazin для более полного ответа. Обновил эту часть еще раз, так как ответ @Borut Tomazin был улучшен.

Вы можете сделать это намного проще, без кода. В Interface Builder установите Line Breakдля UIButton значение Word Wrap. Затем вы можете вставить несколько строк заголовка. Просто нажимайте Option + Returnклавиши, чтобы создать новую строку. Вам также нужно будет добавить это к определяемому пользователем атрибуту времени выполнения в Interface Builder:

titleLabel.textAlignment Number [1]
Тотумус Максимус
источник
5
UILineBreakModeустарели, используйте NSLineBreakModeвместо него
guillaume
2
В последних версиях iOS в этом нет необходимости. См. Ответ @sean.
cbowns
146

Вам не нужно добавлять UILabel в UIButton. Вот только лишние предметы и работа.

Установите эти свойства в titleLabel вашей кнопки.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;//if you want unlimited number of lines put 0

Swift:

button.titleLabel!.lineBreakMode = NSLineBreakMode.ByWordWrapping
button.titleLabel!.numberOfLines = 2//if you want unlimited number of lines put 0
Шон
источник
6
Это 2013 год и на сегодняшний день это самое современное решение.
Клаас
@Blip вы, к сожалению, не можете, и вам нужно сделать это в коде. Возможно, стоит отправить отчет об ошибке в Apple, запрашивая эту функцию.
bpapa
@bpapa Да, я согласен, раскадровки должны быть более гибкими.
Blip
6
Это работает для меня, однако это нарушает поведение кнопки по умолчанию intrinsicContentSize, которое по-прежнему возвращает высоту, соответствующую только одной строке текста. Я исправил это, переопределив кнопку, на intrinsicContentSizeкоторой я установил высоту [self.titleLabel sizeThatFits(CGSizeMake(self.titleLabel.frame.size.width, CGFLOAT_MAX)].height.
Elise
@WillVonUllrich, потому что вы можете изменить принятый ответ только при его редактировании. Я добавил эти ответы к принятому, чтобы он помог людям, которые не смотрят дальше принятого ответа.
Totumus Maximus
88

Вы можете сделать это намного проще, без кода. В Interface Builder установите Line Breakдля UIButton значение Word Wrap. Затем вы можете вставить несколько строк заголовка. Просто нажимайте Option + Returnклавиши, чтобы создать новую строку. Вам также нужно будет добавить это к определяемому пользователем атрибуту времени выполнения в Interface Builder:

titleLabel.textAlignment Number [1]

Это так просто. Надеюсь, это поможет...

Борут Томазин
источник
1
Это решение лучше (меньше объектов, кода), чем принятое в настоящее время, для простых случаев.
Джонатан Жан
1
Вы устанавливаете те же свойства, что и программно, поэтому ваш аргумент «меньше объектов» недействителен. Код может быть меньше. Но это более читабельно.
Выбирайте
О, я думаю, неясно. Спасибо, что попытались уточнить. Не был так сильно обеспокоен тем, что это делается в IB vs Code. Больше связано с тем, что вам не нужно добавлять дополнительную метку с решением Borut, и что он также выполняет то же самое. Но да, оба отлично работают. :)
Джонатан Жан
это действительно ошеломляюще - писать код для такой простой задачи.
Джан Пойразоглу
3
Вы можете достичь той же цели на 100% без кода, добавив определяемый titleLabel.textAlignment пользователем атрибут времени выполнения в Interface Builder и установив его на Number = 1 (значение NSTextAlignmentCenter).
0xced
21
 button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;

button.titleLabel.textAlignment = NSTextAlignmentCenter;

[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
Сурадж К. Томас
источник
Прекрасный! Вам не нужно разделять NSStringвнутреннюю часть setTitle. WordWrapping делает это за вас!
Alex Cio
Мне пришлось разбить строку внутри заголовка набора. Без этого ничего не
вышло
9

Чтобы полностью избежать необходимости редактировать код и, следовательно, создавать подклассы вашего представления, в Xcode5 и выше вы можете следовать предложению Борута Томазина:

В Интерфейсном Разработчике (или раскадровке) установите Разрыв строки на Перенос слов. Затем вы можете вставить несколько строк заголовка. Просто нажмите клавиши Option+, Returnчтобы создать новую строку.

а затем в определяемых пользователем атрибутах времени выполнения вы можете добавить

Путь ключа: titleLabel.textAlignment
Тип: Number
Значение:1

Примечание: это может быть не полностью «перспективным», поскольку мы переводим UITextAlignmentCenterконстанту в ее числовое значение (и эта константа может измениться по мере выпуска новых версий iOS), но в ближайшем будущем это кажется безопасным.

фуринс
источник
0

Вы можете изменить необходимое значение прямо из раскадровки. Нажмите кнопку, перейдите к инспектору удостоверений и добавьте следующую пару "ключ-значение" в раздел «Пользовательские атрибуты среды выполнения»:

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

Арик Сегал
источник