iOS: Jak można animować do nowego ograniczenia autoukładu (wysokość)

123

Nigdy wcześniej nie pracowałem z ograniczeniami autoukładu . Mam małą nową aplikację, nad którą pracuję i zauważyłem, że widoki NIB są domyślnie ustawione na automatyczne układanie. Pomyślałem więc, że skorzystam z okazji, aby z tym popracować i spróbuję dowiedzieć się, dokąd zmierza Apple.

Pierwsze wyzwanie:

Muszę zmienić rozmiar MKMapView i chcę go animować do nowej pozycji. Jeśli zrobię to w sposób, do którego przywykłem:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

... wtedy MKMapView „przyskoczy” z powrotem do swojej pierwotnej wysokości za każdym razem, gdy zostanie zaktualizowany widok rodzeństwa (w moim przypadku tytuł UISegmentedControl jest aktualizowany [myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0]).

Więc, co mam myśleć chcę zrobić, to zmienić więzy MKMapView z równym obszyty widoku nadrzędnego do bycia w stosunku do górnej części UISegmentedControl że został obejmujące:V:[MKMapView]-(16)-[UISegmentedControl]

Chcę, aby wysokość MKMapView została skrócona, tak aby niektóre elementy sterujące pod widokiem mapy były widoczne. Aby to zrobić, myślę, że muszę zmienić ograniczenie ze stałego widoku w pełnym rozmiarze na taki, w którym dół jest ograniczony do góry UISegmentedControl ... i chciałbym, aby był animowany, gdy widok kurczy się do nowego rozmiaru.

Jak się do tego zabrać?

Edytuj - ta animacja nie jest animowana, chociaż dół widoku przesuwa się natychmiast w górę o 170:

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

a nibMapViewConstraintjest podłączony w IB do dolnego ograniczenia przestrzeni w pionie.

Meltemi
źródło
1
Wiem, że możesz łatwo zmienić stałą wartość ograniczenia w bloku [UIView animateWithDuration ..], aby animować zmianę wysokości. Musisz utworzyć IBOutlet dla tego ograniczenia i podłączyć go do swojego xib lub w inny sposób zachować do niego odniesienie, jeśli utworzyłeś go w kodzie (lub zapętlić wszystkie ograniczenia, aby go znaleźć). Nie jestem pewien, jak animować zmiany relatedBy, ale przeczytałem, że powinieneś zmieniać tylko stałą, a nie inne wartości ograniczenia (dla innych wartości utwórz nowe ograniczenie).
yuf
Hmm. pomyślałem, że mógłbym, ale nie jestem animowany. Zmienia się pomyślnie i znajduje się w bloku animacji, ale nie jest animowany!?!
Meltemi
Znalazłem moją odpowiedź tutaj: < stackoverflow.com/questions/12926566/… >
Meltemi
1
Nie zapomnij o [widoku layoutuIfNeeded], to też był mój problem haha. To jest to samo pytanie, które rozwiązało mój problem.
yuf
Możliwy duplikat Jak animować zmiany wiązań?
Senseful

Odpowiedzi:

179

Po zaktualizowaniu ograniczenia:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

Zastąp self.viewodwołaniem do widoku zawierającego.

Ed McManus
źródło
4
to działa dla samego widoku, jednak widoki, które mają ograniczenia do tego widoku, po prostu przesuwają się natychmiast. Co ja robię? ty
dietbacon
7
W razie potrzeby musisz również wywołać układ w tych widokach. jednak tak naprawdę nie działa poprawnie, ponieważ spowoduje to również animację odświeżania widoku. Jak animować dopasowanie wiązania tylko w innych widokach?
ngb
3
Uwaga: jeśli używasz UIViewAnimationOptionBeginFromCurrentStateukładu, ograniczenia zostaną ustawione PRZED animacją!
Robert,
12
Zamiast dzwonić layoutIfNeededpo każdy z tych widoków, po prostu zadzwoń[[self.view superview] layoutIfNeeded];
Flying_Banana
2
@ngb musisz zmienić stałą wiązania wewnątrz bloku animacji. W ten sposób ograniczenie zmienia się wraz z animacją i możesz nadal używać UIViewAnimationOptionBeginFromCurrentState.
Eran Goldin
86

To działa dla mnie (zarówno iOS7, jak i iOS8 +). Kliknij ograniczenie automatycznego układu, które chcesz dostosować (w konstruktorze interfejsu, np. Ograniczenie górne). Następnie uczyń z tego IBOutlet;

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

Animuj w górę;

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

Animuj z powrotem do pierwotnego miejsca

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];
DevC
źródło
2
ŁAŁ!! To naprawdę działa! Ta odpowiedź otworzyła mi oczy. Dziękuję bardzo! - Erik
Erik van der Neut
2
@ErikvanderNeut to też było dla mnie, cieszę się, że było pomocne. Od teraz będę animował ograniczenia, a nie położenie klatek.
DevC
nie przegap dodania: [containerView layoutIfNeeded]; Zapewnia, że ​​wszystkie oczekujące operacje dotyczące układu zostały zakończone PRZED blokiem animateWithDuration.
ingconti
11

Istnieje bardzo dobry tutorial od Apple'a, który wyjaśnia, jak używać animacji z autoukładem. Skorzystaj z tego linku, a następnie znajdź film o nazwie „Automatyczny układ według przykładu” Zawiera on kilka interesujących informacji na temat automatycznego układu, a ostatnia część dotyczy korzystania z animacji.

Glenn
źródło
3

Zrobiłem dostępny ten mały demo . Na bardzo prostym przykładzie pokazano, jak można zmieniać i animować ograniczenia automatycznego układu. Po prostu spójrz na DemoViewController.m .

Jens Schwarzer
źródło
1

Większość ludzi używa autoukładu do układania elementów w swoich widokach i modyfikowania ograniczeń układu w celu tworzenia animacji.

Łatwym sposobem na zrobienie tego bez dużej ilości kodu jest utworzenie UIView, który chcesz animować w Storyboard, a następnie utworzenie ukrytego UIView, w którym chcesz zakończyć UIView. Możesz użyć podglądu w xcode, aby upewnić się, że oba UIViews są tam, gdzie chcesz, aby były. Następnie ukryj końcowy UIView i zamień ograniczenia układu.

Istnieje podfile do zamiany ograniczeń układu o nazwie SBP, jeśli nie chcesz go pisać samodzielnie.

Oto samouczek .

Arjay Waran
źródło
0

Nie ma potrzeby używania więcej IBOutlet referenceograniczenia zamiast tego, można bezpośrednio accesslub updatejuż zastosować ograniczenie albo Programmaticallyz Interface Builderdowolnego widoku, albo z dowolnego widoku korzystającego z KVConstraintExtensionsMasterbiblioteki. Ta biblioteka zarządza również Cumulativezachowaniem NSLayoutConstraint.

Aby dodać ograniczenie wysokości do containerView

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

Aby zaktualizować ograniczenie wysokości w containerView z animacją

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
keshav vishwkarma
źródło