2013-05-21 12 views
5

Così sto cercando di animare alcuni vincoli di layout e sto avendo misera fortuna, io non basta vedere qualsiasi cosa e poi ricevo un messaggio di errore che dice come esso non può soddisfare contemporaneamente tutte vincoli eccprogrammatico NSLayoutConstraint problemi di animazione

Sto usando una classe chiamata PullableView la cui animazione utilizza il vecchio stile [UIView commitAnimation] così l'ho sottoclassata e aggiunta nel mio codice per quello che credo sarebbe stato per i vincoli di animazione ... Non ho avuto tanta fortuna e ho cercato di animarlo o persino di farlo molto di qualsiasi cosa si sta rivelando difficile ho appena ottenuto "Incapace di soddisfare simultaneamente i vincoli" .. Il problema è che sono abbastanza nuovo a questo business dei vincoli quindi non saprei da dove cominciare.

ecco l'errore l'altro è praticamente lo stesso ma per centroY.

"<NSLayoutConstraint:0x7c8a3a0 StyledPullableView:0x905a9b0.centerX == UIView:0x9054680.centerX>", "<NSLayoutConstraint:0x7c6b480 StyledPullableView:0x905a9b0.centerX == UIView:0x9054680.centerX + 128>"

Io naturalmente fare [pullRightView setTranslatesAutoresizingMaskIntoConstraints:NO]; prima di chiamare questo

alcun aiuto apprezzato.

- (void)setOpenedForConstraints:(BOOL)op animated:(BOOL)anim 
{ 
    opened = op; 

    if (anim) 
    {   
     NSLayoutConstraint *constraintX = [NSLayoutConstraint constraintWithItem:self 
                       attribute:NSLayoutAttributeCenterX 
                       relatedBy:NSLayoutRelationEqual 
                        toItem:_parentView 
                       attribute:NSLayoutAttributeCenterX 
                       multiplier:1 
                       constant:0]; 

     NSLayoutConstraint *constraintY = [NSLayoutConstraint constraintWithItem:self 
                       attribute:NSLayoutAttributeCenterY 
                       relatedBy:NSLayoutRelationEqual 
                        toItem:_parentView 
                       attribute:NSLayoutAttributeCenterY 
                       multiplier:1 
                       constant:0]; 

     [_parentView addConstraint:constraintX]; 
     [_parentView addConstraint:constraintY]; 

     constraintX.constant = opened ? self.openedCenter.x : self.closedCenter.x; 
     constraintY.constant = opened ? self.openedCenter.y : self.closedCenter.y; 
    } 

    if (anim) 
    { 

     // For the duration of the animation, no further interaction with the view is permitted 
     dragRecognizer.enabled = NO; 
     tapRecognizer.enabled = NO; 

     //[UIView commitAnimations]; 

     [UIView animateWithDuration:animationDuration 
         animations:^ 
     { 
      [self layoutIfNeeded]; 
     }]; 

    } 
    else 
    { 

     if ([delegate respondsToSelector:@selector(pullableView:didChangeState:)]) 
     { 
      [delegate pullableView:self didChangeState:opened]; 
     } 
    } 
} 

risposta

11

Un paio di pensieri:

  1. si sta creando nuovi vincoli qui. In genere si regola constant di un vincolo esistente. Oppure, se necessario, rimuoverai il vecchio vincolo e ne aggiungerai uno nuovo.

  2. Quando si modifica un vincolo esistente, ci sono due approcci. Uno è quello di iterare attraverso i vincoli della vista, trovando quello in questione, e quindi aggiustando il constant per quello. L'altro approccio (e molto più semplice quando la vista è quella che è stata aggiunta in Interface Builder) consiste nel creare uno IBOutlet per il vincolo direttamente in Interface Builder. Quindi puoi animarlo.

    • This answer, mettendo a fuoco un altro problema, illustra il processo di creazione di IBOutlet per un vincolo e quindi animate il cambiamento del suo valore.

    • Se avete per scorrere i vincoli alla ricerca di vincoli (ad esempio, la raccolta di un vincolo di un'intera collezione che si può aver creato con il linguaggio formato visivo, per esempio), allora la replaceLeadingAndTopWithCenterConstraints illustrato nella this answer potrebbe essere un utile esempio di come si trova un vincolo su una vista esistente. Questo particolare esempio è la rimozione di un vincolo e l'aggiunta di un nuovo, ma è possibile, altrettanto facilmente, una volta trovato il vincolo esistente, regolarne la costante.


io non sono del tutto sicuro della UX si sta andando per, ma diciamo di avere un pannello che si desidera far scorrere verso sinistra dello schermo:

  1. il primo problema è quello che i vincoli che si sono definiti: In questo esempio, mi piacerebbe avere quattro vincoli definiti, tre al superview (vale a dire superiore, inferiore, e di sinistra, ma non destra) e un vincolo di larghezza . E se lo fai in IB, può essere pignolo (ad esempio non puoi rimuovere il vincolo giusto finché non aggiungi il vincolo di larghezza).Assicurati solo che i vincoli siano completamente definiti, ma in minima parte così.

  2. allora posso animare lo scorrimento del pannello fuori dallo schermo semplicemente cambiando la constant del vincolo sinistra:

    - (IBAction)touchUpInsideButton:(id)sender 
    { 
        self.offscreen = !self.offscreen; 
    
        [UIView animateWithDuration:0.5 
            animations:^{ 
             self.panelLeftConstraint.constant = ([self isOffscreen] ? -kHowMuchToSlideOffToLeft : 0.0); 
             [self.view layoutIfNeeded]; 
            }]; 
    } 
    
  3. Si può vedere ora perché era importante assicurarsi che non vi era alcuna ragione vincolo definito. Perché se ho regolato il vincolo di sinistra mentre avevo un vincolo di larghezza e definito un vincolo di destra, sarebbe diventato insoddisfacente. Assicurandomi che i vincoli fossero definiti minimamente (sebbene definiti in modo univoco) all'inizio, posso modificare il vincolo di sinistra e la vista ora si anima come volevo.

+0

Grazie per la risposta, ho approfondiranno attraverso queste ... tolgo anche tutti i vincoli prima di aggiungere quelle nuove ... Anche se lo faccio nella funzione init ... – Genhain

+1

@Genhain penso che sia molto più facile cambiare i vincoli che aggiungere e rimuovere. E sii molto attento a quali vincoli hai definito per la vista in primo luogo. Ad esempio, se dovessi farlo scorrere a sinistra, lo avrei definito con top, bottom, left e width (ma non con il tasto destro!), Quindi posso eseguire l'animazione modificando la costante del vincolo di sinistra . Vedi la risposta rivista. Devo confessare che non ero in grado di decifrare quale fosse l'UX desiderata dal tuo esempio di codice, quindi se chiarisci cosa stai cercando di ottenere, potrei essere più utile. – Rob

+0

Ottima risposta, ma il punto 2 nella tua prima lista è sbagliato. Solo layoutIfNeeded deve trovarsi all'interno del blocco di animazione. – jrturton

Problemi correlati