2013-11-28 6 views
21

Ho due UILabels uno accanto all'altro in fila con le regolazioni sinistra e destra in modo che assomigli al seguente.AutoLayout collega due UILabels per avere la stessa dimensione di carattere

|-Some text left adjusted----------some other text right adjusted-| 

Entrambe le etichette sono adjustsFontSizeToFitWidth = YES e sono collegati tra loro con il seguente vincolo

[NSLayoutConstraint constraintWithItem:_rightLabel 
        attribute:NSLayoutAttributeLeft 
        relatedBy:NSLayoutRelationGreaterThanOrEqual 
        toItem:_leftLabel 
        attribute:NSLayoutAttributeRight 
        multiplier:1 
        constant:10] 

In modo che essi occupano più spazio possono e se non c'è spazio sufficiente per il dimensione del carattere originale verrà abbassata grazie a adjustsFontSizeToFitWidth in modo che nessun testo venga troncato.

Il mio problema è che quando è necessario abbassare la dimensione del carattere a causa del testo lungo, l'altra etichetta deve abbassarne anche la dimensione del carattere in modo che entrambe abbiano la stessa dimensione invece di una che abbia forse il doppio delle altre . Vorrei limitare la dimensione del carattere per abbinare ma ahimè non so come, qualsiasi idea?

+0

Sono riuscito a ottenere qualcosa di simile all'effetto desiderato imponendo un vincolo di larghezza uguale tra le due etichette .. (il ridimensionamento dei caratteri è lo stesso in entrambi gli ultimi due caratteri sono troncati ..) – Aodh

risposta

-1

Si potrebbe provare a utilizzare key-value observing per osservare le modifiche alla proprietà font su un'etichetta e quando lo fa, impostare l'altra etichetta di utilizzare lo stesso tipo di carattere.

nel metodo -viewDidLoad:

// Add self as an observer of _rightLabel's font property 
[_rightLabel addObserver:self forKeyPath:@"font" options:NSKeyValueObservingOptionNew context:NULL]; 

Nella stessa implementazione del controller (auto nel codice sopra frammenti contesto):

// Observe changes to the font property of _rightLabel 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if (object == _rightLabel && [keyPath isEqualToString:@"font"]) { 
     // Set _leftLabel's font property to be the new value set on _rightLabel 
     _leftLabel.font = change[NSKeyValueChangeNewKey]; 
    } 
} 
+0

Non penso che la proprietà del font cambia sempre quando si utilizza 'adjustsFontSizeToFitWidth'. Il valore 'font' rimane invariato ma, una volta visualizzato, viene visualizzato con una dimensione del carattere minore. – Jackson

+0

E [l'unico modo per calcolare la dimensione del carattere rettificato] (http://stackoverflow.com/questions/3669844/how-to-get-uilabel-uitextview-auto-adjusted-font-size/6141770#6141770) è stato deprecato in iOS 7. – Jackson

13

Dal UILabel documentation on adjustsFontSizeToWidth:

Normalmente, il testo dell'etichetta viene disegnato con il carattere specificato in proprietà del carattere. Se questa proprietà è impostata su SÌ, tuttavia, e il testo nella proprietà text supera il rettangolo di delimitazione dell'etichetta, il ricevitore inizia a ridurre la dimensione del carattere fino a quando la stringa non si adatta o viene raggiunta la dimensione minima del carattere.

Ne deduco che il carattere aggiornato è calcolato in tempo a disegnare, e la proprietà font è di sola lettura, non è scritto a. Pertanto, credo che il suggerimento di Andrew di utilizzare KVO sulla proprietà font non funzionerà.

Di conseguenza, per ottenere il risultato desiderato, è necessario calcolare la dimensione del carattere regolato.

Come nota Jackson nei commenti, this very convenient NSString method per ottenere il carattere effettivo è stato deprecato in iOS 7. Tecnicamente, è ancora possibile utilizzarlo fino a quando non viene rimosso.

Un'altra alternativa consiste nel fare il ciclo delle scale dei caratteri finché non ne trovi uno adatto ad entrambe le etichette. Sono stato in grado di farlo funzionare bene; here's a sample project that shows how I did it.

Inoltre, ecco il codice in caso che collegano mai smette di funzionare:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_rightLabel 
                    attribute:NSLayoutAttributeLeft 
                    relatedBy:NSLayoutRelationGreaterThanOrEqual 
                    toItem:_leftLabel 
                    attribute:NSLayoutAttributeRight 
                   multiplier:1 
                    constant:10]; 

    [self.view addConstraint:constraint]; 
} 

- (IBAction)makeRightLabelLongerPressed:(id)sender { 
    self.rightLabel.text = @"some much longer right label text"; 
} 

- (IBAction)adjustLabelSizes:(id)sender { 
    NSLog(@"Attempting to adjust label sizes…"); 

    CGFloat minimumScaleFactor = fmaxf(self.rightLabel.minimumScaleFactor, self.leftLabel.minimumScaleFactor);; 
    UIFont * startingFont = self.rightLabel.font; 

    for (double currentScaleFactor = 1.0; currentScaleFactor > minimumScaleFactor; currentScaleFactor -= 0.05) { 
     UIFont *font = [startingFont fontWithSize:startingFont.pointSize * currentScaleFactor]; 
     NSLog(@" Attempting font with scale %f (size = %f)…", currentScaleFactor, font.pointSize); 

     BOOL leftLabelWorks = [self wouldThisFont:font workForThisLabel:self.leftLabel]; 
     BOOL rightLabelWorks = [self wouldThisFont:font workForThisLabel:self.rightLabel]; 
     if (leftLabelWorks && rightLabelWorks) { 
      NSLog(@" It fits!"); 
      self.leftLabel.font = font; 
      self.rightLabel.font = font; 
      return; 
     } else { 
      NSLog(@" It didn't fit. :-("); 
     } 

    } 

    NSLog(@" It won't fit without violating the minimum scale (%f), so set both to minimum. Some text may get truncated.", minimumScaleFactor); 

    UIFont *minimumFont = [self.rightLabel.font fontWithSize:self.rightLabel.font.pointSize * self.rightLabel.minimumScaleFactor]; 
    self.rightLabel.font = minimumFont; 
    self.leftLabel.font = minimumFont; 
} 

- (BOOL) wouldThisFont:(UIFont *)testFont workForThisLabel:(UILabel *)testLabel { 
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:testFont, NSFontAttributeName, nil]; 
    NSAttributedString *as = [[NSAttributedString alloc] initWithString:testLabel.text attributes:attributes]; 
    CGRect bounds = [as boundingRectWithSize:CGSizeMake(CGRectGetWidth(testLabel.frame), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin) context:nil]; 
    BOOL itWorks = [self doesThisSize:bounds.size fitInThisSize:testLabel.bounds.size]; 
    return itWorks; 
} 

- (BOOL)doesThisSize:(CGSize)aa fitInThisSize:(CGSize)bb { 
    if (aa.width > bb.width) return NO; 
    if (aa.height > bb.height) return NO; 
    return YES; 
} 

Questo approccio potrebbe essere banalmente riscritta in un metodo categoria che sostituisce il metodo deprecato collegato a da Jackson.

+0

Non sono sicuro di comprendere completamente il tuo scenario. Se ho ragione su ciò che penso sia, forse potresti aggiungere una terza etichetta che contiene il testo concatenato dei due che hai descritto. La nuova etichetta sarebbe trasparente, con il solo scopo di stabilire la dimensione del carattere appropriata. per la dimensione dell'etichetta. Quindi le altre due etichette potrebbero semplicemente essere giustificate come appropriato utilizzando le stesse dimensioni del carattere dell'etichetta trasparente. –

+0

@VictorEngel Questo codice stabilisce la dimensione corretta del carattere senza creare una terza etichetta. Prova a scaricare ed eseguire il progetto. –

+0

Sicuro. Stavo solo suggerendo un'alternativa che utilizzava solo il layout automatico. Doveva essere un commento alla domanda originale, non un commento alla tua risposta. Non so come sia finito qui. Mi dispiace per quello –

1

Ho trovato una soluzione migliore. Basta aggiungere agli spazi di testo dall'inizio alla fine a uilabel, che hanno una lunghezza di testo inferiore. E i font saranno uguali.

+1

Questo mi ha fatto ridere - Adoro la semplicità, anche se non funzionerà il 100% delle volte. Se il carattere non è una larghezza fissa, uno spazio non è la larghezza di salvataggio come la maggior parte delle altre lettere. Se hai una lunga stringa con un sacco di "w" (che sono molto ampi) sarà comunque più lunga della stringa corta con lo spazio vuoto. In altre parole, anche se hanno la stessa quantità di caratteri, non hanno sempre la stessa larghezza. Anche se in molti casi sarà abbastanza vicino per funzionare. –

Problemi correlati