2015-10-01 12 views
5

Sto cercando disperatamente di attaccare uno dei miei UILabels all'estremità destra della sua superview mentre la larghezza dell'etichetta è variabile (è un tempo quindi la cosa si sta ingrandendo e dovrebbe espandendo a sinistra, questo viene fatto usando sizeToFit all'interno dell'etichetta quando il testo è impostato).Come incollare UIView sul lato destro del suo superview a livello di codice

Finora ho provato un sacco di cose, ma più vicino ho avuto con:

_elapsedTimeRightConstraint = [NSLayoutConstraint constraintWithItem:_elapsedTimeView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-150]; 

Mentre l'etichetta viene inizialmente impostata su 150px di larghezza. Ma quando modifico la costante, tutto va all'inferno.

_elapsedTimeRightConstraint.constant = (_elapsedTimeView.frame.size.width * -1); 
[self layoutIfNeeded]; 

Quindi la mia domanda è, come faccio align bordi d'uscita di una vista ed è superview (così si attacca a destra) quando la larghezza della visualizzazione secondaria è in continua evoluzione. Ho usato FLKAutoLayout in altre parti del progetto, quindi se questo può essere fatto facilmente con questa struttura, allora la soluzione base di autolayout sarebbe incredibile !!!

+2

Stai creando l'etichetta a livello di codice? In tal caso, assicurati di aver impostato 'translatesAutoResizingMaskIntoConstraints' su' NO'. In secondo luogo dovresti usare 'NSLayoutConstraintTrailing' invece di' NSLayoutConstraintRight' (e principale piuttosto che a sinistra) poiché questo rende il tuo layout funzionante nelle lingue di destra-sinistra. Non dovresti avere -150 per la costante vuoi solo 0 e non hai bisogno di modificare il vincolo perché le etichette regolano automaticamente le loro dimensioni intrinseche mentre il contenuto cambia. Infine, a meno che non stiate facendo qualcosa di superfluo, usate Interface Builder. È molto più facile che programmarlo – Paulw11

risposta

4

Innanzitutto, assicurarsi che translatesAutoresizingMaskIntoConstraints sia impostato su NO, se si sta creando l'etichetta a livello di codice.

Il primo vincolo necessario è "label.trailing = superview.trailing".

[NSLayoutConstraint constraintWithItem:label 
          attribute:NSLayoutAttributeTrailing 
          relatedBy:NSLayoutRelationEqual 
           toItem:superview 
          attribute:NSLayoutAttributeTrailing 
          multiplier:1.f 
           constant:0.f] 

Questo porrà il bordo destro (nelle lingue da sinistra a destra) dell'etichetta sul bordo destro del superview.

Ora sarà necessario un vincolo per la posizione Y.

Nella mia prova, ho centrato verticalmente l'etichetta con il seguente vincolo:

[NSLayoutConstraint constraintWithItem:label 
          attribute:NSLayoutAttributeCenterY 
          relatedBy:NSLayoutRelationEqual 
           toItem:superview 
          attribute:NSLayoutAttributeCenterY 
          multiplier:1.f 
           constant:0.f] 

Ora arriva il trucco!

Ogni volta che si modifica il testo sull'etichetta, è necessario ricalcolare i frame con AutoLayout.

AutoLayout volontà:

1) Chiedi l'etichetta della sua nuova dimensione (in base al suo testo).

2) Regolare il formato dell'etichetta.

3) Pin il bordo posteriore dell'etichetta sul bordo posteriore del superview.


ulteriori ricerche

Il problema con UILabel è che quando si sta utilizzando layout automatico e impostare il testo, le sue intrinsicContentSize cambiamenti, ma non fa scattare un aggiornamento di layout.

Un modo per far rispettare questo senza sottoclasse UILabel è utilizzare il runtime Objective-C.

@interface UILabel (AutoLayout) 

- (void)swz_setText:(NSString*)text; 

@end 

@implementation UILabel (AutoLayout) 

+ (void)load 
{ 
    NSLog(@"Swizzling [UILabel setFont:]..."); 

    Method oldMethod = class_getInstanceMethod(self, @selector(setText:)); 
    Method newMethod = class_getInstanceMethod(self, @selector(swz_setText:)); 

    method_exchangeImplementations(oldMethod, newMethod); 
} 

- (void)swz_setText:(NSString*)text 
{ 
    if (![text isEqualToString:self.text]) { 
     [self setNeedsLayout]; 
    } 
    [self swz_setText:text]; //This now points to "setText:" - not a mistake! 
} 

@end 

In questa categoria, mi sto "valorizzare" setText: implementazione chiamando setNeedsLayout se il testo cambia.

Ora è sufficiente richiamare layoutIfNeeded nel superview per ricalcolare/riallineare il frame dell'etichetta.


Clicca here per il parco giochi (Swift 2.0 - Xcode 7), dove ho provato il mio codice.

Spero che questo aiuti.

0

Ciao qui ci sono alcuni punti per ottenere ciò che si vuole:

  • Set NSLayoutConstraintTrailing costante uguale a 0 e il vincolo principale NSLayoutAttributeLeading impostarlo come maggiore o uguale il valore che si volere.
  • Usa NSLayoutConstraintTrailing e NSLayoutAttributeLeading invece di destra e sinistra per gestire altre lingue Spero che questo aiuta
0
[yourLabel sizeToFit];  
CGRect frame = yourLabel.frame; 
frame.x = parentView.frame.size.width - yourLabel.frame.size.width; 
yourLabel.frame = frame; 

Si ignora completamente la "best practice" di utilizzare le funzioni di layout automatico, ma se si può solo' Lo sopporto ... dovrebbe funzionare. ;-)

Problemi correlati