uilabel не сжимает текст автоматически до размера этикетки

<p>у меня есть эта странная проблема, и я занимаюсь этим уже более 8 часов. в зависимости от ситуации мне нужно динамически вычислять размер <code>uilabels</code>, <br> например <br>мой <code>uiviewcontroller</code> получает событие, и я изменяю размер <code>uilabels</code>. от большего к меньшему. размер моего <code>uilabel</code> становится меньше, и я получаю правильный необходимый размер, но текст в моем <code>uilabel</code> остается прежним, тот же размер шрифта и т.д. мне нужно, чтобы шрифт уменьшился, чтобы весь текст соответствовал <code>uilabel</code>. итак, вопрос в том, как сделать так, чтобы текст соответствовал моему ярлыку с <code>autoshrinking</code> или что-то в этом роде?</p><p>в моем <code>xib</code> проверяется <code>uilabels</code> <code>autoshrink</code>, также<strong> число строк </strong>установлено в 0, а также в моей строке есть новые символы строки (\ n), и я выбрал<strong> linebreakmode </strong>для <code>wordwrap</code>. может быть, кто-то был в такой же ситуации, как я сейчас, и мог бы помочь мне? я был бы очень признателен.</p><p>заранее спасибо!</p><p><strong> правка: </strong><code>uilabel</code> минимальный размер шрифта установлен на 10</p>

<p>если вы все еще ищете лучшее решение, я думаю, это то, что вы хотите:</p><p><em>логическое значение, указывающее, должен ли быть уменьшен размер шрифта, чтобы вписать строку заголовка в ограничивающий прямоугольник метки.</em> (это свойство действует только в том случае, если для свойства numberoflines установлено значение 1.)</p><pre><code>@property(nonatomic) bool adjustsfontsizetofitwidth </code></pre><p><em>логическое значение, указывающее, следует ли корректировать интервал между буквами, чтобы он соответствовал строке внутри прямоугольника границ метки.</em></p><pre><code>@property(nonatomic) bool adjustsletterspacingtofitwidth </code></pre><p> <a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/uilabel\_class/reference/uilabel.html">источник</a> .</p>

<p>вот как я работаю с uilabel <code>autoshrink</code> (особенно для высоты подгонки шрифта надписи на устройстве 4s от 6s plus storyboard) в ios 9.2, xcode 7.2 ...</p><p> <a href="https://i.stack.imgur.com/rtcvf.png"> <img src="https://i.stack.imgur.com/rtcvf.png" alt="enter image description here"> </a> </p><ul> <li>количество строк 0</li> <li>разрывы строк: клип</li> <li>автоусадка: минимальный масштаб шрифта 0,25</li> </ul>

<p><code>minimumfontsize</code> устарела в ios 6.</p><p>поэтому используйте <code>minimumscalefactor</code> вместо <code>minmimumfontsize</code>.</p><pre><code>lbl.adjustsfontsizetofitwidth=yes; lbl.minimumscalefactor=0.5; </code></pre>

<p>также мое решение - логическое label.adjustsfontsizetofitwidth = yes; но. в интерфейсе builder необходимо установить переключатель «обтекание словами» на «<strong>clip</strong>» . затем автоматически сжимать метки. это очень важно.</p>

<p>вы можете написать как</p><pre><code>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]; </code></pre><p>вы можете рассчитать количество строк, как это</p><pre><code>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 </code></pre><hr><pre><code>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"; </code></pre><p>надеюсь, что это поможет вам: -) жду вашего ответа </p>

<p>это для swift 3 под управлением xcode 8.2.1 (8c1002) </p><p>лучшее решение, которое я нашел, это установить фиксированную ширину в раскадровке или ib на этикетке. установите ваши ограничения с ограничением на полях. в ваш viewdidload добавьте следующие строки кода:</p><pre><code>override func viewdidload() { super.viewdidload() label.numberoflines = 1 label.adjustsfontsizetofitwidth = true label.minimumscalefactor = 0.5 } </code></pre><p> <a href="https://i.stack.imgur.com/kxhch.png"> <img src="https://i.stack.imgur.com/kxhch.png" alt="label constraints to margin"> </a> </p><p> <a href="https://i.stack.imgur.com/entcx.png"> <img src="https://i.stack.imgur.com/entcx.png" alt="fixed width label constraints to margin"> </a> </p><p> <a href="https://i.stack.imgur.com/xtkfc.png"> <img src="https://i.stack.imgur.com/xtkfc.png" alt="attributes inspector"> </a> </p><p>это работает как шарм, и оно не переходит на новую строку и сокращает текст до ширины надписи без каких-либо странных проблем и работает в swift 3.</p>

<p>в swift 3 (программно) я должен был сделать это:</p><pre><code>let lbl = uilabel() lbl.numberoflines = 0 lbl.linebreakmode = .byclipping lbl.adjustsfontsizetofitwidth = true lbl.minimumscalefactor = 0.5 lbl.font = uifont.systemfont(ofsize: 15) </code></pre>

<p>ну, в конце концов, я не нашел свой ответ. и я думаю, что автоусадка не работает для нескольких строк. в итоге я воспользовался предложением в этой ссылке: <a href="https://stackoverflow.com/questions/9059631/autoshrink-on-a-uilabel-with-multiple-lines">автоматическое сжатие uilabel с несколькими строками</a> </p><p>решением является вычисление высоты текста при заданной ширине и, если текст больше, уменьшение размера шрифта, а затем повторение его до тех пор, пока высота не станет равной или меньшей требуемого размера.</p><p>я не понимаю, почему это так сложно реализовать. если я что-то упустил, каждый может поправить меня :)</p>

<p>я думаю, что вы можете написать ниже код <strong>после alloc init label</strong> </p><pre><code>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]; </code></pre><p><strong>это работает со мной нормально используйте его</strong></p>

<p>два года спустя, и эта проблема все еще существует ...</p><p>в ios 8/xcode 6.1 я иногда обнаруживал, что мой <code>uilabel</code> (созданный в <code>uitableviewcell</code>, с включенным autolayout и гибкими ограничениями, чтобы в нем было достаточно места) не изменял свой размер, чтобы соответствовать текстовой строке.</p><p>решение, как и в предыдущие годы, состояло в том, чтобы установить текст и<em> затем </em>call <code>sizetofit</code>.</p><pre><code>-(uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { . . . cell.lblcreatedat.text = [note getcreateddateasstring]; [cell.lblcreatedat sizetofit]; } </code></pre><p>(вздох.)</p>

<p>в ios 9 мне просто нужно было:</p><ol> <li>добавьте ограничения слева и справа от метки в суперпредставление.</li> <li>установите режим разрыва строки в отсечение в ib.</li> <li>установите количество строк в 1 в ib.</li> </ol><p>кто-то порекомендовал установить число строк равным 0, но для меня это просто заставило ярлык перейти на несколько строк ...</p>

<p>это отличный вопрос, потому что кажется, что это будет частью встроенной функциональности <code>uikit</code> или связанной с ней инфраструктуры. вот хороший наглядный пример вопроса:</p><p><img src="https://cdn-images-1.medium.com/max/1600/1*ycfvpmysgkudgykwkpuaha.gif" alt="font resizing animation"></p><p>там нет простого пути, но это определенно возможно. один из способов сделать это - программно пробовать шрифты разных размеров, пока не найдете тот, который подходит достаточно близко к границам вида. вы можете сделать это с помощью функции <code>boundingrect()</code> <code>nsstring</code> или <code>nsattributedstring</code>. например:</p><pre><code>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 </code></pre><p>вы можете выполнить бинарный поиск, чтобы быть более эффективным, чем полный метод грубой силы. есть также некоторые соображения, которые являются более сложными, в том числе правильная упаковка word и производительность кэширования шрифтов ios, если вы ищете что-то действительно надежное.</p><p>если вам нужно просто показать текст на экране, я разработал надежную реализацию в swift, которую я также использую в производственном приложении. это подкласс <code>uiview</code> с эффективным автоматическим масштабированием шрифта для любого вводимого текста, включая несколько строк. чтобы использовать его, вы просто должны сделать что-то вроде:</p><pre><code>let view = aktextview() // use a simple or fancy nsattributedstring view.attributedtext = .init(string: "some text here") // add to the view hierarchy somewhere </code></pre><p>это оно! вы можете найти полный источник здесь: <a href="https://github.com/flicktype/accessibilitykit">https://github.com/flicktype/accessibilitykit</a> </p><p>надеюсь это поможет!</p>

<p>не работает, если <code>numberoflines > 1</code> то, что я сделал, поставило условие</p><pre><code>if(lblreclocation.text.length > 100) lblreclocation.font = [uifont fontwithname:@"app\_font\_name" size:10]; </code></pre>

<p>вот как это сделать. предположим, что следующее messagelabel - это метка, которую вы хотите получить желаемый эффект. теперь попробуйте эти простые строки кода:</p><pre><code> //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. </code></pre>

<p>опаздываю на вечеринку, но так как у меня было дополнительное требование иметь одно слово в строке, это одно дополнение помогло мне:</p><p><code>label.numberoflines = [labelstring componentsseparatedbystring:@" "].count;</code></p><p> <a href="https://developer.apple.com/library/ios/documentation/uikit/reference/uilabel\_class/index.html#//apple\_ref/occ/instp/uilabel/adjustsfontsizetofitwidth">apple docs</a> сказать:</p><blockquote> <p>обычно текст метки рисуется шрифтом, который вы указали в свойстве font. однако если для этого свойства задано значение yes, а текст в свойстве text превышает ограничивающий прямоугольник метки, получатель начинает уменьшать размер шрифта до тех пор, пока строка не будет соответствовать или не будет достигнут минимальный размер шрифта. <strong>в ios 6 и более ранних версиях это свойство действует только в том случае, если для свойства numberoflines установлено значение 1.</strong></p> </blockquote><p>но это ложь. ложь, я говорю вам! это верно для всех версий ios. в частности, это верно при использовании <code>uilabel</code> внутри <code>uicollectionviewcell</code>, размер которого определяется ограничениями, динамически настраиваемыми во время выполнения с помощью пользовательского макета (например, <code>self.menucollectionviewlayout.itemsize = size</code>).</p><p>таким образом, при использовании в сочетании с <code>adjustsfontsizetofitwidth</code> и <code>minimumscalefactor</code>, как упоминалось в предыдущих ответах, программная установка <code>numberoflines</code> на основе количества слов решает проблему автоматического сжатия. выполнение чего-либо подобного на основе количества слов или даже количества символов может привести к «достаточно близкому» решению.</p>

<p>в swift 4 (программно): </p><pre><code>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) </code></pre>

<p><strong> swift 4, xcode 9.4.1 </strong></p><p>решение, которое сработало для меня: у меня была<strong> метка в ячейке представления коллекции </strong>, и текст метки обрезался .. установите атрибуты, как показано ниже на раскадровке</p><pre><code>lines = 0 linebreak = word wrap set yourlabel's leading and trailing constraint = 0 (using autolayout) </code></pre>