2013-05-21 9 views
5

Więc próbuję animowanie pewne ograniczenia układu i mam nieszczęśliwy traf, ja po prostu nie widzę niczego, a następnie pojawia się komunikat o błędzie, jak to nie może jednocześnie spełniać wszystkie ograniczenia co itpZautomatyzowane NSLayoutConstraint problemy animacji

Używam klasy o nazwie PullableView, której animacja używa starego stylu [UIView commitAnimation], więc podklasowałem ją i dodałem w moim kodzie na to, co moim zdaniem byłoby za animowanie ograniczeń ... Bez takiego szczęścia i próby ożywienia go lub nawet zmusić go do zrobienia wiele czegokolwiek okazuje się być trudnym, po prostu dostaję "Nie można jednocześnie zaspokoić ograniczeń". Problem jest całkiem nowy w tym biznesie ograniczającym, więc nie wiedziałbym, od czego zacząć.

tutaj jest błąd, drugi jest prawie taki sam, ale dla centerY.

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

I oczywiście zrobić [pullRightView setTranslatesAutoresizingMaskIntoConstraints:NO]; przed wywołaniem tej

jakąkolwiek pomoc mile widziana.

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

Odpowiedz

11

Kilka myśli:

  1. Jesteś tutaj tworzenie nowych wiązań. Zazwyczaj dostosujesz constant istniejącego ograniczenia. Lub, jeśli to konieczne, usuniesz stare więzienie i dodasz nowe.

  2. Podczas zmiany istniejącego wiązania istnieją dwa podejścia. Jednym z nich jest powtórzenie więzów widoku, znalezienie danego, a następnie dostosowanie do tego celu. Inne podejście (i znacznie łatwiejsze, gdy widok jest dodany w Konstruktorze interfejsów), polega na utworzeniu IBOutlet dla prawa ograniczenia w programie Interface Builder. Wtedy możesz ożywić to.

    • This answer, skupiając się na inny problem ilustruje proces tworzenia IBOutlet na ograniczenie, a następnie animowanie zmianę wartości.

    • Jeśli trzeba wykonać iterację ograniczeń poszukujących ograniczeń (np wybierając jedną ograniczenie z całej kolekcji, które może być utworzone z językiem formacie wizualnym, na przykład), a następnie replaceLeadingAndTopWithCenterConstraints zilustrowane w this answer może być pomocny przykład tego, jak znaleźć ograniczenie dla istniejącego widoku. Ten konkretny przykład polega na usunięciu ograniczenia i dodaniu nowego, ale równie łatwo można, po znalezieniu istniejącego ograniczenia, dostosować jego stałą.


Nie jestem do końca pewny UX masz zamiar, ale powiedzmy, że masz panel chcesz zsunąć się po lewej stronie ekranu:

  1. Pierwszy problem to zdefiniowane ograniczenia: W tym przykładzie zdefiniowane są cztery ograniczenia, trzy do widoku superwizyjnego (górny, dolny i lewy, ale , a nie po prawej) i ograniczenie szerokości. . A jeśli robisz to w IB, może to być trudne (np. Nie możesz usunąć odpowiedniego ograniczenia, dopóki nie dodasz ograniczenia szerokości).Tylko upewnij się, że ograniczenia są w pełni zdefiniowane, ale w minimalnym stopniu.

  2. Wtedy możemy animować przesuwanie panelu wyłączonym ekranie tylko przez zmianę constant z lewej przymusu:

    - (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. Widać teraz, dlaczego to było ważne, aby upewnić się, że nie było w porządku ograniczenie zdefiniowane. Ponieważ jeśli skorygowałbym lewe ograniczenie, gdy miałem zdefiniowane ograniczenie szerokości i zdefiniowane ograniczenie prawe, wówczas stałoby się ono niesprawne. Upewniając się, że ograniczenia zostały zdefiniowane minimalnie (chociaż jednoznacznie zdefiniowane) na początku, mogę zmienić lewe ograniczenie, a widok animuje się teraz tak, jakbym tego chciał.

+0

Dzięki za odpowiedź, będę zagłębiać przez nich ... Ja również usunąć wszystkie ograniczenia przed dodaniem nowych ... Chociaż to zrobić w funkcji init ... – Genhain

+1

@Genhain myślę, że to znacznie łatwiej zmienić ograniczenia niż dodawanie i usuwanie. I bądź bardzo ostrożny, które ograniczenia zdefiniowałeś dla widoku w pierwszej kolejności. Na przykład, gdybym miał go przesunąć w lewo, zdefiniowałbym to z górną, dolną, lewą i szeroką (ale nie prawą!), A następnie mogę animować, zmieniając stałą lewego ograniczenia . Zobacz poprawioną odpowiedź. Muszę wyznać, że nie byłem w stanie odcyfrować, jaki jest twój pożądany UX z próbki kodu, więc jeśli wyjaśnisz, co próbujesz osiągnąć, mogę być bardziej pomocny. – Rob

+0

Świetna odpowiedź, ale punkt 2 na pierwszej liście jest błędny. Tylko layoutIfNeeded musi znajdować się wewnątrz bloku animacji. – jrturton