UILabel не автоматично скорочує текст, щоб відповідати розміру мітки


119

У мене є ця дивна проблема, і я займаюся цим питанням вже більше 8 годин. Залежно від ситуації я повинен UILabelsдинамічно обчислювати розмір,
наприклад,
мій UIViewControllerотримує подію, і я змінюю UILabelsрозмір. від більшого до меншого. Розмір мого UILabelстає меншим, і я отримую потрібний потрібний розмір, але текст у моєму UILabelзалишається однаковим, однаковий розмір шрифту і т. Д. Мені потрібен шрифт, щоб він став меншим, щоб весь текст міг відповідати UILabel. Отже, питання полягає в тому, як зробити так, щоб текст підходив до моєї мітки autoshrinkingчи щось подібне?

У моєму xib, UILabels autoshrinkвстановлено прапорець, також кількість рядків встановлено на 0, а також мій рядок має нові символи рядка (\ n), і я вибрав linebreakmode для wordwrap. Можливо, хтось опинився в тій же ситуації, що я зараз, і міг би мені допомогти? Я б дуже цінував це.

Спасибі заздалегідь!

EDIT: UILabel мінімальний розмір шрифту встановлено на 10


який мінімальний розмір вашого шрифту для встановленої мітки, будь ласка, додайте.
AJPatel

Відповіді:


159

Якщо ви все ще шукаєте кращого рішення, я думаю, що саме цього ви хочете:

Булеве значення, що вказує, чи слід зменшувати розмір шрифту, щоб розмістити заголовковий рядок у обмежувальному прямокутнику мітки (ця властивість діє лише тоді, коли для numberOfLinesвластивості встановлено 1).

При встановленні цього властивості minimumScaleFactorОБОВ'ЯЗКОВО встановити (хороший за замовчуванням 0,5).

Швидкий

var adjustsFontSizeToFitWidth: Bool { get set }

Ціль-С

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

Булеве значення, яке вказує, чи слід відрегулювати відстань між літерами, щоб відповідати рядку в прямокутнику меж межі.

Швидкий

var allowsDefaultTighteningForTruncation: Bool { get set }

Ціль-С

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Джерело .


18
Як сторонне позначення, minimumFontSizeв iOS 6.0 застаріло. Використовуйте minimumScaleFactorзамість цього.
менше

14
Так, автоматична усадка не працює для декількох ліній в UILabel. Спробуйте уявити собі таке: у вас текст з декількома рядками, ви хочете його зменшити, щоб він «підходив» до ширини. Тож чи слід стискати весь текст, щоб він вміщувався в один рядок, або слова залишалися в одному рядку і стискалися, щоб відповідати кожній ширині? Останнє - найпоширеніший випадок, але не забувайте, що слова також налаштовані на розташування у декілька рядків. Навіть якщо автоматичне розташування тексту вимкнено, вам доведеться стикатися з кожним рядком тексту, що мають різний розмір шрифту, оскільки не кожне слово відповідатиме ширині.
менше

2
Я думаю, що ця відповідь із категорією тут досить хороша, це може бути навіть те, що ви реалізували в будь-якому випадку. У програмі Apple API щось не вистачає, або, можливо, вони просто не бачать скорочення, це звичайний випадок використання для декількох рядків статичного тексту .
менше

1
ну так, це хороший момент, але все одно, я думаю, якщо я встановлю кількість рядків на 0, це якесь чітке твердження, що може бути один або кілька рядків. І автоматичне посилання може бути визначене за номерами рядків, які я здогадуюсь. Але все одно, дякую за очищення речей. Я думав, що роблю щось не так. Категорія - це гарна ідея, я думаю, я збираюся зробити це в іншому проекті, де мені це знадобиться. Вдячний за вашу допомогу, удачі;)
Лукас

4
@lester Він повинен скорочуватися, щоб весь текст був видно у кількості рядків, оголошених для мітки, враховуючи її поточні розміри. Не потрібно намагатися зробити кожен рядок різного розміру. Я дуже здивований, що не може цього зрозуміти. Так що, якщо у мене є (потенційно) довга рядок для відображення я можу або мати кілька рядків або мати його автоматичного розмір, але з обидва. Це прекрасно.
devios1

125

Ось так я отримую Autoshrinkроботу з UILabel (особливо для висоти розміщення шрифту етикетки на пристрої 4s від 6s Plus Storyboard) в iOS 9.2, Xcode 7.2 ...

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

  • Кількість рядків 0
  • Лінійні перерви: Кліп
  • Автосшивання: Мінімальна шрифт шрифту 0,25

15
Це 3 інгредієнти, необхідні для того, щоб етикетка фактично скоротилася, мені не вистачало налаштування розриву лінії кліпу. Крім того, якщо його суміжні з іншими мітками (які також можуть автоматично скорочуватися), тоді потрібно встановити пріоритети стиснення / обіймати або вказати явні обмеження ширини чи висоти. Це має бути прийнята на даний момент відповідь.
Корей Хінтон

3
Кількість рядків зробив це для мене! Дякую
Майкл

Переконайтеся, що на вашій етикетці є всі обмеження, особливо провідні та зворотні.
Машхаді

2
Я намагався з тими ж параметрами в Xcode8 і виявив, що не працює. Будь ласка, допоможіть мені, якщо хтось має ідею з цього приводу.
Ганеш

75

minimumFontSize застаріла в iOS 6.

Тому використовуйте minimumScaleFactorзамість minmimumFontSize.

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

Швидкий 5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5

Добре відповів. Вирішили мою проблему. Спасибі
Абдул Ясін

1
@AntonMatosov, ні, це не так!
Юліан Онофрей

2
Так, це так (зараз) - якщо ви також встановите перерви рядка на "Урізати хвіст замість обгортання слів ..."
TheEye

21

також моє рішення - булева мітка.adjustsFontSizeToFitWidth = ТАК; АЛЕ Ви повинні в інтерфейсі Builder переключити Word Wrapping на " CLIP ". Потім автозв’язати мітки. Це дуже важливо.


3
Тільки коли я змінив з "Обертання слів" на "Кліп", автоматичне посилання працювало на мене.
NicJ

Коли я змінив обертання слів на кліп, мені вдалося змусити його змінити розмір у мітці з нульовими рядками. Хлопчик, було б добре, якби це було задокументовано.
призначенийNerd

12

У Swift 3 (програмно) мені довелося це зробити:

let lbl = UILabel()
lbl.numberOfLines = 0
lbl.lineBreakMode = .byClipping
lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5
lbl.font = UIFont.systemFont(ofSize: 15)

5

Можна писати як

UILabel *reviews = [[UILabel alloc]initWithFrame:CGRectMake(14, 13,270,30)];//Set frame
reviews.numberOfLines=0;
reviews.textAlignment = UITextAlignmentLeft;
reviews.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:12];
reviews.textColor=[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.8]; 
reviews.backgroundColor=[UIColor clearColor];

Ви можете обчислити кількість таких рядків

CGSize maxlblSize = CGSizeMake(270,9999);
CGSize totalSize = [reviews.text sizeWithFont:reviews.font 
              constrainedToSize:maxlblSize lineBreakMode:reviews.lineBreakMode];

CGRect newFrame =reviews.frame;
newFrame.size.height = totalSize.height;
reviews.frame = newFrame;

CGFloat reviewlblheight = totalSize.height;

int lines=reviewlblheight/12;//12 is the font size of label

UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(140,220 , 100, 25);//set frame as your requirement
lbl.font=[UIFont fontWithName:@"Arial" size:20];
[lbl setAutoresizingMask:UIViewContentModeScaleAspectFill];
[lbl setLineBreakMode:UILineBreakModeClip];
lbl.adjustsFontSizeToFitWidth=YES;//This is main for shrinking font
lbl.text=@"HelloHelloHello";

Сподіваюся, що це допоможе вам :-) чекаю вашої відповіді


Так що якщо встановити кількість рядків для моєї мітки, текст буде автоматично зв'язаний тоді?
Лукас

якщо ваш вміст не в ширині, це займе наступний рядок
Birju

Ей, я зробив так, як ти запропонував, але це не працює, чому кількість рядків допоможе мені?
Лукас

ви праві, я спробував це не корисно, але я знайшов рішення для вас, як це моя наступна відповідь
Біржу

lbl.adjustsFontSizeToFitWidth = ТАК; Працювали для мене!
Розробник

4

Ну врешті-решт я не знайшов своєї відповіді. І я думаю, автоматичне посилання не працює для декількох рядків. Я в кінцевому підсумку використовував пропозицію за цим посиланням: автоматичне посилання на UILabel з кількома рядками

Рішення полягає в тому, щоб визначити висоту тексту за заданою шириною, а якщо текст більший, зменшити розмір шрифту, а потім виконувати його так само, поки висота не дорівнює або менше потрібного вам розміру.

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


Згідно з іншими відповідями тут, ключовим, що бракувало, було те, що потрібно встановити програму Wrapping для Word на "Clip". Це контрінтуїтивно, але це потрібно, щоб отримати UILabel для автоматичного скорочення потрібним способом. Це працює з багаторядковою UILabel.
Дункан Беббідж

4

Це для Swift 3 під керуванням Xcode 8.2.1 (8C1002)

Найкраще рішення, яке я знайшов, - встановити на етикетці фіксовану ширину вашої дошки розкадрів або IB. Встановлюйте свої обмеження з обмеженням на поля. У свій поглядDidLoad додайте наступні рядки коду:

override func viewDidLoad() {
            super.viewDidLoad()

            label.numberOfLines = 1
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.5
        }

обмеження мітки для маржі

обмеження мітки фіксованої ширини для поля

атрибути інспектора

Це спрацьовувало як шарм, і воно не переливається на новий рядок і скорочує текст, щоб відповідати ширині етикетки без будь-яких дивних питань і працює в Swift 3.


4

Це чудове запитання, адже, здається, це було б частиною вбудованої UIKitфункціональності чи пов'язаної з цим рамки. Ось хороший наочний приклад питання:

Анімація розміру шрифту

Немає цього простого шляху, але це, безумовно, можливо. Один із способів зробити це - програматично спробувати різні розміри шрифту, поки не знайдете той, який підходить досить близько до меж перегляду. Ви можете досягти цього за допомогою boundingRect()функції NSStringабо NSAttributedString. Наприклад:

let string = "This is a test"
let infiniteSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height:CGFloat.greatestFiniteMagnitude)
let size = string.boundingRect(with: infiniteSize, options: [], attributes: [.font: UIFont.systemFont(ofSize: avgSize)] context: nil).size

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

Якщо вам цікаво лише простий показ тексту на екрані, я розробив надійну реалізацію в Swift, яку я також використовую у виробничому додатку. Це UIViewпідклас з ефективним, автоматичним масштабуванням шрифту для будь-якого вхідного тексту, включаючи кілька рядків. Щоб його використовувати, ви просто зробите щось на кшталт:

let view = AKTextView()
// Use a simple or fancy NSAttributedString
view.attributedText = .init(string: "Some text here")
// Add to the view hierarchy somewhere

Це воно! Ви можете знайти повне джерело тут: https://github.com/FlickType/AccessibilityKit

Сподіваюся, це допомагає!


1
Листопад 2018: З'являється, що FlickType і AccessibilityKit перейшли у приватний режим або видалено.
Кріс Павелліо

3

У iOS 9 мені просто довелося:

  1. Додайте обмеження зліва та праворуч від мітки до нагляду.
  2. Встановіть режим розриву лінії на відсікання в ІБ.
  3. В IB встановіть кількість рядків на 1.

Хтось рекомендував встановити кількість рядків до 0, але для мене це просто змусило мітку перейти на кілька рядків ...


Це зробило для мене трюк. Щойно я вибрав a UILabelі a UITextFieldу статичній комірці та натиснув "Вирішити проблеми з автоматичною розстановкою" та "Додати пропущені обмеження". Все вишикувались, але Автошинку потрібно було знати відстань до мітки, для чого "Додати відсутні обмеження" не додав обмежень.
Адріан

2

Я думаю, що ви можете написати наступний код після присвоєння init Label

UILabel* lbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 280, 50)];
lbl.text = @"vbdsbfdshfisdhfidshufidhsufhdsf dhdsfhdksbf hfsdh fksdfidsf sdfhsd fhdsf sdhfh sdifsdkf ksdhfkds fhdsf dsfkdsfkjdhsfkjdhskfjhsdk fdhsf ";
[lbl setMinimumFontSize:8.0];
[lbl setNumberOfLines:0];
[lbl setFont:[UIFont systemFontOfSize:10.0]];
lbl.lineBreakMode = UILineBreakModeWordWrap;
lbl.backgroundColor = [UIColor redColor];
[lbl sizeToFit];
[self.view addSubview:lbl];

Зі мною це чудово працює


1
дякую, але це не вирахує або зменшить шрифт до мінімально необхідного, як я розумію, а також чому ваш мінімальний шрифт більший, ніж звичайний?
Лукас

2

Два роки і ця проблема все ще існує ...

У iOS 8 / XCode 6.1 я інколи виявляв, що мій UILabel(створений уUITableViewCell з увімкненою функцією AutoLayout та гнучкими обмеженнями, щоб у ньому було багато місця) не змінює себе, щоб підходити до текстового рядка.

Рішенням, як і в попередні роки, було встановити текст, а потім зателефонувати sizeToFit.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    . . .
    cell.lblCreatedAt.text = [note getCreatedDateAsString];
    [cell.lblCreatedAt sizeToFit];
}

(Зітхає)


1

Ось як це зробити. Скажімо, наступне повідомлення "Мітка" - це мітка, для якої ви бажаєте отримати бажаний ефект. Тепер спробуйте такі прості рядки кодів:

    //SET THE WIDTH CONSTRAINTS FOR LABEL.
    CGFloat constrainedWidth = 240.0f;//YOU CAN PUT YOUR DESIRED ONE,THE MAXIMUM WIDTH OF YOUR LABEL.
 //CALCULATE THE SPACE FOR THE TEXT SPECIFIED.
    CGSize sizeOfText=[yourText sizeWithFont:yourFont constrainedToSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
    UILabel *messageLabel=[[UILabel alloc] initWithFrame:CGRectMake(20,20,constrainedWidth,sizeOfText.height)];
    messageLabel.text=yourText;
    messageLabel.numberOfLines=0;//JUST TO SUPPORT MULTILINING.

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

1

не працює, якщо numberOfLines > 1 я зробив такий стан,

if(lblRecLocation.text.length > 100)
    lblRecLocation.font = [UIFont fontWithName:@"app_font_name" size:10];

0

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

label.numberOfLines = [labelString componentsSeparatedByString:@" "].count;

Apple Docs кажуть:

Зазвичай текст мітки малюється шрифтом, який ви вказали у властивості шрифту. Якщо для цього властивості встановлено YES, а текст у властивості тексту перевищує обмежувальний прямокутник мітки, приймач починає зменшувати розмір шрифту, поки рядок не підходить або не буде досягнуто мінімального розміру шрифту. В iOS 6 і новіших версіях ця властивість ефективна лише тоді, коли властивість numberOfLines встановлена ​​на 1.

Але це брехня. Неправду я вам кажу! Це справедливо для всіх версій iOS. Зокрема, це справедливо при використанні в UILabelмежах, UICollectionViewCellдля якого розмір визначається обмеженнями, які динамічно регулюються під час виконання за допомогою користувацького макета (наприклад self.menuCollectionViewLayout.itemSize = size).

Тому при використанні в поєднанні з adjustsFontSizeToFitWidthі minimumScaleFactor, як вже згадувалися в попередніх відповідях, програмна настройка на numberOfLinesоснові кількості слів вирішити проблему Autoshrink. Виконання чогось подібного на основі кількості слів або навіть кількості символів може призвести до "достатньо близького" рішення.


0

У Swift 4 (програмно):

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200.0, height: 200.0))
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0

label.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."

view.addSubview(label)

0

Швидкий 4, Xcode 9.4.1

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

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.