UILabel non riduce automaticamente il testo per adattarlo alle dimensioni dell'etichetta


119

Ho questo strano problema, e im trattare con esso per più di 8 ore ora .. A seconda della situazione devo calcolare UILabelsdimensioni in modo dinamico,
ad esempio,
il mio UIViewControllerriceve un evento e cambiare i UILabelsdimensioni. da più grande a più piccolo. La dimensione del mio UILabelsi riduce e ottengo la dimensione corretta necessaria, ma il testo nel mio UILabelrimane lo stesso, la stessa dimensione del carattere e così via UILabel. Quindi la domanda è come adattare il testo alla mia etichetta autoshrinkingo qualcosa del genere?

Nel mio xib, UILabels autoshrinkè selezionato, anche il numero di righe è impostato su 0, e anche la mia stringa ha nuovi simboli di riga (\ n), e ho selezionato la modalità di interruzione di riga su wordwrap. Forse qualcuno si trovava nella stessa situazione in cui mi trovo ora e potrebbe aiutarmi? Lo apprezzerei davvero.

Grazie in anticipo!

MODIFICA: UILabel la dimensione minima del carattere è impostata su 10


qual è la dimensione minima del tuo carattere per l'etichetta che hai impostato per favore aggiungi.
AJPatel

Risposte:


159

Nel caso tu stia ancora cercando una soluzione migliore, penso che questo sia quello che vuoi:

Un valore booleano che indica se la dimensione del carattere deve essere ridotta per adattare la stringa del titolo al rettangolo di delimitazione dell'etichetta (questa proprietà è efficace solo quando la numberOfLinesproprietà è impostata su 1).

Quando si imposta questa proprietà, minimumScaleFactorDEVE essere impostata anche (un buon valore predefinito è 0,5).

veloce

var adjustsFontSizeToFitWidth: Bool { get set }

Objective-C

@property(nonatomic) BOOL adjustsFontSizeToFitWidth;

Un valore booleano che indica se la spaziatura tra le lettere deve essere regolata per adattare la stringa all'interno del rettangolo dei limiti dell'etichetta.

veloce

var allowsDefaultTighteningForTruncation: Bool { get set }

Objective-C

@property(nonatomic) BOOL allowsDefaultTighteningForTruncation;

Fonte .


18
Come nota a margine, minimumFontSizeè deprecato in iOS 6.0. Usa minimumScaleFactorinvece.
lester

14
Sì, la riduzione automatica non funziona per più righe in UILabel. Prova a immaginare questo: hai un testo con più righe, vuoi ridurlo in modo che "si adatti" alla larghezza. Quindi dovrebbe ridurre l'intero testo per adattarlo a una riga o le parole rimanere sulla stessa riga e ridursi per adattarsi a ciascuna larghezza? Quest'ultimo è il caso più comune, ma non dimenticare che anche le parole sono impostate per disporsi su più righe. Anche se la disposizione automatica del testo è disabilitata, dovrai affrontare ogni riga del testo con una dimensione del carattere diversa, poiché non tutte le parole si adatteranno alla larghezza.
lester

2
Penso che questa risposta con una categoria qui sia abbastanza buona, potrebbe anche essere quella che hai implementato comunque. Questo è sicuramente qualcosa che manca nell'API di Apple, o forse semplicemente non vedono il restringimento dovrebbe essere un caso d'uso comune per più righe di testo statico .
lester

1
beh sì, questo è un buon punto, ma comunque, penso che se imposto il numero di linee a 0, questa è una specie di dichiarazione chiara che potrebbero esserci una o più linee. E il restringimento automatico potrebbe essere determinato dai numeri di riga immagino .. Ma comunque, grazie per aver chiarito le cose. Pensavo di fare qualcosa di sbagliato. Una categoria è una buona idea, immagino che lo farò in un altro progetto in cui ne avrò bisogno. Apprezzo il tuo aiuto, buona fortuna;)
Lukas

4
@lester Dovrebbe ridursi in modo che l'intero testo sia visibile nel numero di righe dichiarato per l'etichetta date le sue dimensioni attuali. Non è necessario tentare di rendere ogni riga una dimensione diversa. Sono davvero sorpreso che non riesca a capirlo. Quindi, se ho una (potenzialmente) lungo stringa da visualizzare posso neanche avere più linee o farla automatico delle dimensioni, non entrambi. È adorabile.
devios1

125

Questo è il modo in cui ottengo il Autoshrinklavoro di UILabel (in particolare per l'altezza del font dell'etichetta che si adatta al dispositivo 4s da 6s Plus Storyboard) in iOS 9.2, Xcode 7.2 ...

inserisci qui la descrizione dell'immagine

  • Il numero di righe è 0
  • Interruzioni di riga: clip
  • Riduzione automatica: scala caratteri minima 0,25

15
Questi sono i 3 ingredienti necessari affinché un'etichetta si restringa effettivamente, mi mancava l'impostazione dell'interruzione di riga della clip. Inoltre, se è adiacente ad altre etichette (che potrebbero anch'esse ridursi automaticamente), è necessario impostare le priorità di compressione / abbraccio o fornire limitazioni esplicite di larghezza o altezza. Questa dovrebbe essere la risposta attualmente accettata.
Korey Hinton

3
Il numero di righe lo ha fatto per me! Grazie
Michael

Assicurati che la tua etichetta abbia tutti i vincoli, in particolare iniziale e finale.
Mashhadi

2
Ho provato con le stesse opzioni in Xcode8 e ho trovato che non funzionava. Per favore aiutami se qualcuno ha l'idea su questo.
Ganesh

75

minimumFontSize è deprecato in iOS 6.

Quindi usa minimumScaleFactorinvece di minmimumFontSize.

lbl.adjustsFontSizeToFitWidth = YES
lbl.minimumScaleFactor = 0.5

Swift 5

lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5

Ben risposto. Ho risolto il mio problema. Grazie
Abdul Yasin

1
@AntonMatosov, no, non è così!
Iulian Onofrei

2
Sì, lo fa (ora) - se imposti anche le interruzioni di riga su Truncate Tail invece di Word Wrap ...
TheEye

21

anche la mia soluzione è il booleano label.adjustsFontSizeToFitWidth = YES; MA. Nell'interfaccia Builder è necessario impostare l'opzione A capo automatico su " CLIP ". Quindi restringere automaticamente le etichette. Questo è molto importante.


3
Solo quando sono passato da "A capo automatico" a "Clip", Autoshrink ha funzionato per me.
NicJ

Quando ho cambiato il ritorno a capo automatico in clip, sono stato effettivamente in grado di ridimensionarlo in un'etichetta con zero righe. Ragazzo, sarebbe carino se fosse documentato.
DesignatedNerd

12

In Swift 3 (a livello di programmazione) ho dovuto fare questo:

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

5

Puoi scrivere mi piace

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

Puoi calcolare il numero di righe in questo modo

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

Spero che questo ti aiuti :-) in attesa della tua risposta


quindi se imposti il ​​numero di righe sulla mia etichetta, il testo si restringerà automaticamente?
Lukas

se il tuo contenuto è fuori larghezza, ci vorrà la riga successiva
Birju

hey ho fatto come mi hai suggerito, ma non funziona, perché il numero di righe mi aiuterebbe?
Lukas

hai ragione ho provato non è utile ma ho trovato una soluzione per te fai così la mia prossima risposta
Birju

lbl.adjustsFontSizeToFitWidth = SI; Ha funzionato per me!
Sviluppatore

4

Alla fine non ho trovato la mia risposta. E penso che l'autorestringimento non funzioni per più righe. Ho finito per usare il suggerimento in questo link: restringimento automatico su un'etichetta UIL con più righe

La soluzione è calcolare l'altezza del testo a una data larghezza e, se il testo è più grande, ridurre la dimensione del carattere e poi ripetere lo stesso fino a quando l'altezza è uguale o inferiore alla dimensione necessaria.

Non capisco perché dovrebbe essere così difficile da implementare. Se mi manca qualcosa, tutti sono i benvenuti a correggermi :)


Come per altre risposte qui, la cosa fondamentale che mancava era che devi impostare A capo automatico su "Clip". È controintuitivo, ma è necessario per fare in modo che un'etichetta UIL si restringa automaticamente nel modo desiderato. Funziona con un'etichetta UIL su più righe.
Duncan Babbage

4

Questo è per Swift 3 con Xcode 8.2.1 (8C1002)

La soluzione migliore che ho trovato è impostare una larghezza fissa nel tuo Storyboard o IB sull'etichetta. Imposta i tuoi vincoli con vincolo ai margini. Nella tua viewDidLoad aggiungi le seguenti righe di codice:

override func viewDidLoad() {
            super.viewDidLoad()

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

vincoli dell'etichetta al margine

vincoli di etichetta a larghezza fissa al margine

ispettore attributi

Ha funzionato come un fascino e non trabocca su una nuova riga e riduce il testo per adattarlo alla larghezza dell'etichetta senza problemi strani e funziona in Swift 3.


4

È un'ottima domanda, perché sembra che ormai faccia parte della UIKitfunzionalità incorporata o di un framework correlato. Ecco un buon esempio visivo della domanda:

Animazione di ridimensionamento dei caratteri

Non c'è un modo semplice per aggirarlo, ma è sicuramente possibile. Un modo per eseguire questa operazione è provare a livello di codice dimensioni di caratteri diverse finché non ne trovi una che si adatti ragionevolmente vicino ai limiti della visualizzazione. Puoi farlo con la boundingRect()funzione di NSStringo NSAttributedString. Per esempio:

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

Puoi fare una ricerca binaria per essere più efficiente di un approccio completo alla forza bruta. Ci sono anche alcune considerazioni che sono un po 'più coinvolte, tra cui il corretto avvolgimento delle parole e le prestazioni di memorizzazione nella cache dei caratteri iOS, se stai cercando qualcosa di veramente robusto.

Se ti interessa solo mostrare il testo sullo schermo in modo semplice, ho sviluppato un'implementazione robusta in Swift, che sto utilizzando anche in un'app di produzione. È una UIViewsottoclasse con ridimensionamento automatico e efficiente dei caratteri per qualsiasi testo di input, comprese più righe. Per usarlo, devi semplicemente fare qualcosa come:

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

Questo è tutto! Puoi trovare la fonte completa qui: https://github.com/FlickType/AccessibilityKit

Spero che questo ti aiuti!


1
Nov 2018: sembra che FlickType e AccessibilityKit siano diventati privati ​​o siano stati rimossi.
Chris Paveglio

3

In iOS 9 dovevo solo:

  1. Aggiungi vincoli da sinistra e destra dell'etichetta alla superview.
  2. Impostare la modalità di interruzione di riga su clipping in IB.
  3. Impostare il numero di righe su 1 in IB.

Qualcuno ha consigliato di impostare il numero di righe su 0, ma per me questo ha semplicemente fatto sì che l'etichetta andasse su più righe ...


Questo ha funzionato per me. Avevo appena selezionato un UILabele un UITextFieldin una cella statica e ho fatto clic su "Risolvi problemi di layout automatico" e "Aggiungi vincoli mancanti". Tutto era allineato, ma Autoshrink aveva bisogno di conoscere la distanza dall'etichetta, per la quale "Aggiungi vincoli mancanti" non aggiungeva un vincolo.
Adrian

2

Penso che tu possa scrivere il seguente codice dopo alloc 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];

Funziona bene con me. Usalo


1
grazie, ma questo non calcolerà o ridurrà il carattere al minimo necessario come ho capito, e anche perché il tuo carattere minimo è più grande del normale?
Lukas

2

Due anni dopo, e questo problema è ancora in circolazione ...

In iOS 8 / XCode 6.1, a volte ho scoperto che my UILabel(creato in a UITableViewCell, con AutoLayout attivato e vincoli flessibili in modo che avesse molto spazio) non si ridimensionava per adattarsi alla stringa di testo.

La soluzione, come negli anni precedenti, era impostare il testo e poi chiamare sizeToFit.

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

(Sospiro.)


1

Ecco come farlo: supponiamo che il seguente messaggio Etichetta sia l'etichetta con cui desideri ottenere l'effetto desiderato, quindi prova queste semplici righe di codice:

    //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 grazie per la tua risposta, ma non ho bisogno di calcolare l'altezza dell'etichetta, ho una dimensione fissa e, a seconda di ciò, il mio carattere deve essere più piccolo se necessario.
Lukas

1

non funziona se numberOfLines > 1 quello che ho fatto ha creato una condizione come questa-

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

0

Arrivando tardi alla festa, ma poiché avevo il requisito aggiuntivo di avere una parola per riga, questa aggiunta ha fatto il trucco per me:

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

Apple Docs dice:

Normalmente, il testo dell'etichetta viene disegnato con il carattere specificato nella proprietà del carattere. Se questa proprietà è impostata su YES, tuttavia, e il testo nella proprietà text supera il rettangolo di delimitazione dell'etichetta, il destinatario inizia a ridurre la dimensione del carattere finché la stringa non si adatta o non viene raggiunta la dimensione minima del carattere. In iOS 6 e versioni precedenti, questa proprietà è valida solo quando la proprietà numberOfLines è impostata su 1.

Ma questa è una bugia. Una bugia ti dico! È vero per tutte le versioni di iOS. In particolare, questo è vero quando si utilizza a UILabelall'interno di UICollectionViewCella la cui dimensione è determinata da vincoli regolati dinamicamente in fase di esecuzione tramite layout personalizzato (es. self.menuCollectionViewLayout.itemSize = size).

Quindi, se utilizzato insieme a adjustsFontSizeToFitWidthe minimumScaleFactor, come menzionato nelle risposte precedenti, l'impostazione programmatica numberOfLinesbasata sul conteggio delle parole ha risolto il problema del restringimento automatico. Fare qualcosa di simile in base al conteggio delle parole o anche al conteggio dei caratteri potrebbe produrre una soluzione "abbastanza vicina".


0

In Swift 4 (a livello di programmazione):

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

La soluzione che ha funzionato per me: avevo un'etichetta all'interno di una cella della vista raccolta e il testo dell'etichetta veniva tagliato. Imposta gli attributi come di seguito su Storyboard

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.