2013-11-20 4 views
5

Ho un UIView che ha un UILabel come sottoview in esso.Il vincolo di animazione di Autolayout non anima le sottoview

Ora posso cambiare la larghezza della UIView con un'animazione (cambiando costante di proprietà del vincolo) e chiamare layoutIfNeeded in UIView animare ...)

La vista è il ridimensionamento normale, ma l'UILabel (visualizzazione secondaria) cambia la dimensione del carattere alla dimensione 'fine' ma non ha animato correttamente come la visualizzazione uiview.

Secondo la sessione del WWDC 2012, le sottoview dovrebbero animare se solo la costante del superview viene modificata.

UILabel ha una scala di caratteri minima di 0,1 che è inferiore al ridimensionamento del carattere.

risposta

4

stavo lottando animare un ridimensionamento UILabel cambiando il suo width vincolo. L'etichetta disponeva di adjustsFontSizeToFitWidth e minimumScaleFactor set.

L'ho risolto impostando le etichette "contentMode" su UIViewContentModeScaleAspectFit. Per impostazione predefinita per le etichette è UIViewContentModeLeft.

2

Non penso che sia possibile animare le dimensioni del testo in questo modo. L'unico modo in cui posso pensare di farlo è creare una vista dell'istantanea dell'etichetta, aggiungere quella vista sull'etichetta, fare l'animazione, quindi rimuovere la vista dell'istantanea. Questo codice sposta leggermente il testo più piccolo verso il basso, ma sembra piuttosto buono, con solo un movimento molto piccolo quando si rimuove l'etichetta e si rimuove la vista dell'immagine. La vista piccola che contiene l'etichetta aveva una dimensione di 185x36 e l'etichetta presentava vincoli di 20 per ciascun lato di smallView e 8 per la parte superiore e 7 per la parte inferiore. Aggiungo gli stessi vincoli in codice alla vista dell'immagine.

@interface ViewController() 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *widthCon; // width constraint on smallView 
@property (weak,nonatomic) IBOutlet UIView *smallView; // view that the label is embedded in 
@property (weak,nonatomic) IBOutlet UILabel *label; 
@end 

@implementation ViewController 

- (IBAction)shrinkView:(id)sender { 

    UIView *snapshot = [self.label snapshotViewAfterScreenUpdates:YES]; 
    [snapshot setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [self.smallView addSubview:snapshot]; 
    [self.smallView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-20-[snapshot]-20-|" options:0 metrics:nil views:@{@"snapshot":snapshot}]]; 
    NSLayoutConstraint *topCon = [NSLayoutConstraint constraintWithItem:snapshot attribute:NSLayoutAttributeTop relatedBy:0 toItem:self.smallView attribute:NSLayoutAttributeTop multiplier:1 constant:8]; 
    NSLayoutConstraint *bottomCon = [NSLayoutConstraint constraintWithItem:self.smallView attribute:NSLayoutAttributeBottom relatedBy:0 toItem:snapshot attribute:NSLayoutAttributeBottom multiplier:1 constant:7]; 
    [self.smallView addConstraints:@[topCon,bottomCon]]; 
    [self.smallView layoutSubviews]; 
    self.label.alpha = 0; 
    self.widthCon.constant = 100; 
    topCon.constant = 18; 
    bottomCon.constant = 10; 
    [UIView animateWithDuration:.5 animations:^{ 
      [self.view layoutIfNeeded]; 
     } completion:^(BOOL finished) { 
      self.label.alpha = 1; 
      [snapshot removeFromSuperview]; 
     }]; 
} 

Dopo Edit:

C'è un modo per animare la vista in modo che l'etichetta anima anche giù piuttosto che andare immediatamente alla sua dimensione finale. Devi animare il vincolo direttamente con un timer (guarda la spiegazione a circa 31 minuti nel video del WWDC 2012, "Le migliori pratiche per la padronanza del layout automatico"). Questo funziona per animare le dimensioni dell'etichetta, ma la modifica della dimensione del carattere è saltata e non sembra così buona. Se si dispone di un vincolo di larghezza alla vista che l'etichetta è nella (e l'etichetta ha vincoli ai due lati), allora si può fare questo:

-(IBAction)animateSizeChange:(id)sender { 
    [NSTimer scheduledTimerWithTimeInterval:.001 target:self selector:@selector(doStuff:) userInfo:Nil repeats:YES]; 
} 

-(void)doStuff:(NSTimer *) aTimer { 
    self.widthCon.constant -= .2; 
    if (self.widthCon.constant <90) [aTimer invalidate]; 
} 
+0

il codice su after-edit con il timer sembra sfortunatamente anche molto schifoso ..:/ –

+1

l'idea dell'istantanea è molto hacky e non dovrebbe essere affrontata in questo modo, non credi? –

+0

@ Christian'fuzi'Orgler, no, non penso che sia un hacky. Apple utilizza questo "trucco" in alcune delle proprie animazioni. Inoltre, qual è l'alternativa? Per quanto riguarda il tuo primo commento, sì è nervoso, questo è quello che ho detto - l'ho incluso solo per mostrare un modo per animare una sottoview di una vista, che a volte funziona bene, se non stai cercando di ridimensionare il testo. – rdelmar