UILabel verkleinert Text nicht automatisch, um ihn an die Etikettengröße anzupassen


119

Ich habe dieses seltsame Problem und beschäftige mich jetzt seit mehr als 8 Stunden damit. Je nach Situation muss ich die UILabelsGröße dynamisch berechnen ,
z. B. empfange
ich UIViewControllerein Ereignis und ändere die UILabelsGröße. von größer zu kleiner. Die Größe meiner UILabelSchrift wird kleiner und ich bekomme die richtige benötigte Größe, aber der Text in meiner UILabelbleibt gleich, die gleiche Schriftgröße usw. Ich brauche die Schrift, um kleiner zu werden, damit der gesamte Text passt UILabel. Die Frage ist also, wie der Text zu meinem Etikett passt autoshrinkingoder so?

In meinem xib, UILabels autoshrinkwird geprüft, auch Anzahl der Zeilen auf 0 gesetzt ist, und auch neue Liniensymbole (\ n) mein String hat, und ich habe ausgewählt linebreak zu wordwrap. Vielleicht war jemand in der gleichen Situation wie ich und könnte mir helfen? Das würde ich sehr schätzen.

Danke im Voraus!

BEARBEITEN: Die UILabel minimale Schriftgröße ist auf 10 eingestellt


Was ist die Mindestgröße Ihrer Schriftart für das von Ihnen festgelegte Etikett? Bitte fügen Sie hinzu.
AJPatel

Antworten:


159

Falls Sie immer noch nach einer besseren Lösung suchen, ist dies meiner Meinung nach das, was Sie wollen:

Ein boolescher Wert, der angibt, ob die Schriftgröße reduziert werden soll, um die Titelzeichenfolge in das Begrenzungsrechteck der Beschriftung einzufügen (diese Eigenschaft ist nur wirksam, wenn die numberOfLinesEigenschaft auf 1 festgelegt ist).

Wenn Sie diese Eigenschaft minimumScaleFactorfestlegen , MUSS auch festgelegt werden (ein guter Standardwert ist 0,5).

Schnell

var adjustsFontSizeToFitWidth: Bool { get set }

Ziel c

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

Ein boolescher Wert, der angibt, ob der Abstand zwischen Buchstaben so angepasst werden soll, dass die Zeichenfolge in das Begrenzungsrechteck der Beschriftung passt.

Schnell

var allowsDefaultTighteningForTruncation: Bool { get set }

Ziel c

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Quelle .


18
Als Nebenbemerkung minimumFontSizeist in iOS 6.0 veraltet. Verwenden Sie minimumScaleFactorstattdessen.
Lester

14
Ja, das automatische Verkleinern funktioniert nicht für mehrere Zeilen in UILabel. Versuchen Sie sich das vorzustellen: Sie haben Text mit mehreren Zeilen, Sie möchten ihn verkleinern, damit er mit der Breite "passt". Sollte also der gesamte Text verkleinert werden, damit er in eine Zeile passt, oder sollten Wörter in derselben Zeile bleiben und verkleinert werden, um in jede Breite zu passen? Letzteres ist der häufigste Fall, aber vergessen Sie nicht, dass die Wörter auch so eingestellt sind, dass sie sich in mehreren Zeilen anordnen. Selbst wenn die automatische Anordnung des Textes deaktiviert ist, müssen Sie sich mit jeder Textzeile mit einer anderen Schriftgröße auseinandersetzen, da nicht jedes Wort zur Breite passt.
Lester

2
Ich denke, diese Antwort mit einer Kategorie hier ist ziemlich gut, es könnte sogar das sein, was Sie sowieso implementiert haben. Dies ist definitiv etwas, was in der Apple API fehlt, oder vielleicht sehen sie einfach nicht, dass das Verkleinern ein häufiger Anwendungsfall für mehrere Zeilen statischen Textes sein sollte .
lester

1
Nun ja, das ist ein guter Punkt, aber ich denke, wenn ich die Anzahl der Zeilen auf 0 setze, ist das eine klare Aussage, dass es eine oder mehrere Zeilen geben könnte. Und Autoshrink könnte durch die Zeilennummern, denke ich, abgeschreckt werden. Aber trotzdem, danke, dass Sie die Dinge geklärt haben. Ich dachte, ich mache etwas falsch. Eine Kategorie ist eine gute Idee, ich denke, ich werde das in einem anderen Projekt tun, in dem ich das brauche. Schätzen Sie Ihre Hilfe, viel Glück;)
Lukas

4
@lester Es sollte verkleinert werden, damit der gesamte Text in der Anzahl der Zeilen sichtbar ist, die für das Etikett in Anbetracht seiner aktuellen Abmessungen deklariert wurden. Es muss nicht versucht werden, jede Zeile auf eine andere Größe zu bringen. Ich bin wirklich überrascht, dass es das nicht herausfinden kann. Wenn ich also eine (möglicherweise) lange Zeichenfolge anzeigen möchte, kann ich entweder mehrere Zeilen oder eine automatische Größenänderung haben, nicht beide. Das ist schön.
Devios1

125

Auf diese Weise Autoshrinkfunktioniert UILabel in iOS 9.2, Xcode 7.2 ...

Geben Sie hier die Bildbeschreibung ein

  • Die Anzahl der Zeilen ist 0
  • Zeilenumbrüche: Clip
  • Autoshrink: Minimum Font Scale 0.25

15
Dies sind die 3 Zutaten, die benötigt werden, damit ein Etikett tatsächlich schrumpft. Mir fehlte die Einstellung für den Zeilenumbruch. Wenn es an andere Beschriftungen angrenzt (die ebenfalls automatisch verkleinert werden können), müssen Komprimierungs- / Umarmungsprioritäten festgelegt oder explizite Einschränkungen für Breite oder Höhe festgelegt werden. Dies sollte die aktuell akzeptierte Antwort sein.
Korey Hinton

3
Anzahl der Zeilen hat es für mich getan! Vielen Dank
Michael

Stellen Sie sicher, dass Ihr Etikett alle Einschränkungen aufweist, insbesondere das Führen und Nachlaufen.
Mashhadi

2
Ich habe mit den gleichen Optionen in Xcode8 versucht und festgestellt, dass es nicht funktioniert. Bitte helfen Sie mir, wenn jemand die Idee dazu hat.
Ganesh

75

minimumFontSize ist in iOS 6 veraltet.

Verwenden Sie also minimumScaleFactoranstelle von minmimumFontSize.

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

Swift 5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5

Gut beantwortet. Mein Problem wurde gelöst. Vielen Dank
Abdul Yasin

1
@AntonMatosov, nein, das tut es nicht!
Iulian Onofrei

2
Ja, das tut es (jetzt) ​​- wenn Sie auch die Zeilenumbrüche auf "Schwanz
abschneiden"

21

Meine Lösung ist auch das boolesche Label.adjustsFontSizeToFitWidth = YES; ABER. Sie müssen im Interface Builder den Word Wrapping-Schalter auf " CLIP " stellen. Dann schrumpfen Sie die Etiketten automatisch. Dies ist sehr wichtig.


3
Erst als ich von "Zeilenumbruch" zu "Clip" wechselte, funktionierte Autoshrink für mich.
NicJ

Als ich den Zeilenumbruch in "Clip" geändert habe, konnte ich die Größe in einem Etikett mit null Zeilen ändern. Junge, es wäre schön, wenn dies dokumentiert würde.
DesignatedNerd

12

In Swift 3 (programmatisch) musste ich Folgendes tun:

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

5

Du kannst gerne schreiben

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];

Sie können die Anzahl der Zeilen so berechnen

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";

Hoffe das hilft dir :-) warte auf deine Antwort


Wenn also die Anzahl der Zeilen auf meinem Etikett festgelegt wird, wird der Text dann automatisch verkleinert?
Lukas

Wenn Ihr Inhalt nicht breit ist, wird die nächste Zeile angezeigt
Birju

Hey, ich habe getan, wie du vorgeschlagen hast, aber es funktioniert nicht. Warum würde mir die Anzahl der Zeilen helfen?
Lukas

Sie haben Recht, ich habe versucht, es ist nicht nützlich, aber ich habe eine Lösung gefunden, damit Ihnen meine nächste Antwort gefällt
Birju

lbl.adjustsFontSizeToFitWidth = YES; Hat für mich gearbeitet!
Entwickler

4

Am Ende habe ich meine Antwort nicht gefunden. Und ich denke, der Autoshrink funktioniert nicht für mehrere Zeilen. Am Ende habe ich in diesem Link einen Vorschlag verwendet: Autoshrink auf einem UILabel mit mehreren Zeilen

Die Lösung besteht darin, die Texthöhe bei gegebener Breite zu berechnen. Wenn der Text größer ist, verkleinern Sie die Schriftgröße und wiederholen Sie den Vorgang, bis die Höhe der gewünschten Größe entspricht oder darunter liegt.

Ich verstehe nicht, warum dies so schwer umzusetzen sein sollte. Wenn mir etwas fehlt, kann mich jeder gerne korrigieren :)


Wie bei anderen Antworten hier, fehlte der Schlüssel, dass Sie den Zeilenumbruch auf "Clip" setzen mussten. Es ist nicht intuitiv, aber dies ist erforderlich, damit ein UILabel nach Ihren Wünschen automatisch verkleinert wird. Dies funktioniert mit einem mehrzeiligen UILabel.
Duncan Babbage

4

Dies ist für Swift 3 mit Xcode 8.2.1 (8C1002)

Die beste Lösung, die ich gefunden habe, besteht darin, eine feste Breite in Ihrem Storyboard oder IB auf dem Etikett festzulegen. Setzen Sie Ihre Einschränkungen mit Einschränkung auf Ränder. Fügen Sie in Ihrem viewDidLoad die folgenden Codezeilen hinzu:

override func viewDidLoad() {
            super.viewDidLoad()

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

Beschriftungsbeschränkungen für den Rand

Beschränkungen für Beschriftungen mit fester Breite am Rand

Attributinspektor

Dies funktionierte wie ein Zauber und es läuft nicht in eine neue Zeile über und verkleinert den Text, um die Breite des Etiketts ohne seltsame Probleme anzupassen, und funktioniert in Swift 3.


4

Das ist eine großartige Frage, denn es scheint, dass dies UIKitmittlerweile Teil der integrierten Funktionalität oder eines verwandten Frameworks ist. Hier ist ein gutes visuelles Beispiel für die Frage:

Größenänderung der Animation

Es gibt keinen einfachen Weg, aber es ist definitiv möglich. Eine Möglichkeit, dies zu tun, besteht darin, programmgesteuert verschiedene Schriftgrößen auszuprobieren, bis Sie eine finden, die den Grenzen der Ansicht angemessen nahe kommt. Sie können dies mit der boundingRect()Funktion von NSStringoder erreichen NSAttributedString. Beispielsweise:

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

Sie können eine binäre Suche durchführen, um effizienter zu sein als ein vollständiger Brute-Force-Ansatz. Es gibt auch einige Überlegungen, die etwas komplizierter sind, einschließlich des korrekten Zeilenumbruchs und der Caching-Leistung von iOS-Schriftarten, wenn Sie nach etwas wirklich Robustem suchen.

Wenn Sie den Text nur auf einfache Weise auf dem Bildschirm anzeigen möchten, habe ich in Swift eine robuste Implementierung entwickelt, die ich auch in einer Produktions-App verwende. Es ist eine UIViewUnterklasse mit effizienter, automatischer Schriftskalierung für jeden Eingabetext, einschließlich mehrerer Zeilen. Um es zu benutzen, würden Sie einfach etwas tun wie:

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

Das ist es! Die vollständige Quelle finden Sie hier: https://github.com/FlickType/AccessibilityKit

Hoffe das hilft!


1
November 2018: Es wird angezeigt, dass FlickType und AccessibilityKit privat wurden oder entfernt wurden.
Chris Paveglio

3

In iOS 9 musste ich nur:

  1. Fügen Sie der Übersicht Ansichten links und rechts von der Beschriftung hinzu.
  2. Stellen Sie den Zeilenumbruchmodus in IB auf Clipping ein.
  3. Setzen Sie die Anzahl der Zeilen in IB auf 1.

Jemand hat empfohlen, die Anzahl der Zeilen auf 0 zu setzen, aber für mich hat dies nur dazu geführt, dass das Etikett mehrere Zeilen umfasst ...


Das hat den Trick für mich getan. Ich hatte gerade a UILabelund a UITextFieldin einer statischen Zelle ausgewählt und auf "AutoLayout-Probleme beheben" und "Fehlende Einschränkungen hinzufügen" geklickt. Alles stimmte überein, aber Autoshrink musste den Abstand zum Etikett kennen, für den "Add Missing Constraints" keine Einschränkung hinzufügte.
Adrian

2

Ich denke, Sie können folgenden Code schreiben, nachdem Sie init Label zugewiesen haben

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];

Es funktioniert gut mit mir Verwenden Sie es


1
Vielen Dank, aber dies berechnet oder verkleinert die Schrift nicht auf das erforderliche Minimum, und warum ist Ihre minimale Schrift größer als normal?
Lukas

2

Zwei Jahre später, und dieses Problem gibt es immer noch ...

In iOS 8 / XCode 6.1 stellte ich manchmal fest, dass sich meine Größe UILabel(erstellt in a UITableViewCell, mit aktiviertem AutoLayout und flexiblen Einschränkungen, sodass genügend Speicherplatz vorhanden ist) nicht an die Textzeichenfolge anpasste.

Die Lösung bestand wie in den Vorjahren darin, den Text festzulegen und dann aufzurufen sizeToFit.

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

(Seufzer.)


1

Gehen Sie wie folgt vor: Angenommen, die folgende NachrichtLabel ist die Bezeichnung, mit der Sie den gewünschten Effekt erzielen möchten. Probieren Sie jetzt diese einfache Codezeile aus:

    //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.

Hey, danke für deine Antwort, aber ich muss die Höhe des Etiketts nicht berechnen, ich habe eine feste Größe und abhängig davon muss meine Schrift bei Bedarf kleiner werden.
Lukas

1

funktioniert nicht, wenn numberOfLines > 1 Was ich getan habe, eine Bedingung wie diese gemacht hat-

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

0

Als ich zu spät zur Party kam, aber da ich zusätzlich ein Wort pro Zeile haben musste, hat dieser eine Zusatz den Trick für mich getan:

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

Apple Docs sagen:

Normalerweise wird der Beschriftungstext mit der Schriftart gezeichnet, die Sie in der Schriftart-Eigenschaft angegeben haben. Wenn diese Eigenschaft jedoch auf JA gesetzt ist und der Text in der Texteigenschaft das Begrenzungsrechteck des Etiketts überschreitet, beginnt der Empfänger, die Schriftgröße zu reduzieren, bis die Zeichenfolge passt oder die Mindestschriftgröße erreicht ist. In iOS 6 und früheren Versionen ist diese Eigenschaft nur wirksam, wenn die numberOfLines-Eigenschaft auf 1 festgelegt ist.

Aber das ist eine Lüge. Eine Lüge, die ich dir sage! Dies gilt für alle iOS-Versionen. Dies gilt insbesondere für die Verwendung eines UILabelinnerhalb eines, UICollectionViewCellfür das die Größe durch Einschränkungen bestimmt wird, die zur Laufzeit über ein benutzerdefiniertes Layout dynamisch angepasst werden (z. B. self.menuCollectionViewLayout.itemSize = size).

In Verbindung mit adjustsFontSizeToFitWidthund minimumScaleFactor, wie in den vorherigen Antworten erwähnt, numberOfLineslöste die programmgesteuerte Einstellung basierend auf der Wortanzahl das Problem des automatischen Schrumpfens. Wenn Sie etwas Ähnliches basierend auf der Wortanzahl oder sogar der Zeichenanzahl tun, kann dies zu einer "nah genug" Lösung führen.


0

In Swift 4 (programmatisch):

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

Swift 4, Xcode 9.4.1

Die Lösung, die für mich funktioniert hat: Ich hatte eine Beschriftung in einer Sammlungsansichtszelle und der Beschriftungstext wurde gekürzt. Stellen Sie die Attribute im Storyboard wie folgt ein

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.