Jak animować zmiany ograniczeń?

Aktualizuję starą aplikację za pomocą AdBannerView i gdy nie ma reklamy, zsuwa się z ekranu. Gdy pojawia się reklama, przesuwa się ona na ekranie. Podstawowe rzeczy.

Stary styl, ustawiłem klatkę w bloku animacji. Nowy styl, mam IBOutlet do ograniczenia, które określa pozycję Y, w tym przypadku jest to odległość od dołu superview, i zmodyfikować stałą.

- (void)moveBannerOffScreen {
    [UIView animateWithDuration:5
             animations:^{
                          _addBannerDistanceFromBottomConstraint.constant = -32;
                     }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    [UIView animateWithDuration:5
             animations:^{
                         _addBannerDistanceFromBottomConstraint.constant = 0;
             }];
    bannerIsVisible = TRUE;
}

I banner porusza się, dokładnie tak, jak oczekiwano, ale bez animacji.

UPDATE: i re-watched WWDC12 video " Best Practices for Mastering Auto Layout ", który obejmuje animację. Omawia sposób aktualizacji ograniczeń za pomocą CoreAnimation.

Tutaj wpisz opis obrazkaTutaj wpisz opis obrazka

Próbowałem z poniższym kodem, ale uzyskać dokładnie takie same wyniki.

- (void)moveBannerOffScreen {
    _addBannerDistanceFromBottomConstraint.constant = -32;
    [UIView animateWithDuration:2
                     animations:^{
                         [self.view setNeedsLayout];
                     }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    _addBannerDistanceFromBottomConstraint.constant = 0;
    [UIView animateWithDuration:2
                     animations:^{
                         [self.view setNeedsLayout];
                     }];
    bannerIsVisible = TRUE;
}

Na marginesie, sprawdzałem wiele razy i jest to wykonywane w głównym wątku.

Author: hashier, 2012-09-27

13 answers

Dwie ważne Uwagi:

  1. Musisz wywołać layoutIfNeeded wewnątrz bloku animacji. Apple zaleca wywołanie go raz przed blokiem animacji, aby upewnić się, że wszystkie oczekujące operacje układu zostały zakończone

  2. Należy wywołać go w widoku nadrzędnym (np. self.view), a nie w widoku podrzędnym, który ma dołączone ograniczenia. Spowoduje to aktualizację wszystkich ograniczonych widoków, w tym animowanie innych widoków, które mogą być ograniczone do widoku, którego ograniczenie zostało zmienione (np. Widok B jest dołączony do dołu widoku A i właśnie zmieniono górne przesunięcie widoku A i chcesz, aby Widok B animował z nim)

Spróbuj tego:

Objective-C

- (void)moveBannerOffScreen {
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = -32;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen { 
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = 0;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = TRUE;
}

Swift 3

UIView.animate(withDuration: 5) {
    self._addBannerDistanceFromBottomConstraint.constant = 0
    self.view.layoutIfNeeded()
}
 1525
Author: g3rv4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 18:55:58

Doceniam udzieloną odpowiedź, ale myślę, że byłoby miło posunąć się nieco dalej.

Podstawowa animacja bloku z dokumentacji

[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
     // Make all constraint changes here
     [containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];

Ale tak naprawdę jest to bardzo uproszczony scenariusz. Co zrobić, jeśli chcę animować ograniczenia podglądu podrzędnego za pomocą metody updateConstraints?

Blok animacji wywołujący podwidywalną metodę updateConstraints

[self.view layoutIfNeeded];
[self.subView setNeedsUpdateConstraints];
[self.subView updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionLayoutSubviews animations:^{
    [self.view layoutIfNeeded];
} completion:nil];

Metoda updateConstraints jest nadpisana w podklasie UIView i musi wywołać super na końcu metoda.

- (void)updateConstraints
{
    // Update some constraints

    [super updateConstraints];
}

Poradnik AutoLayout pozostawia wiele do życzenia, ale warto go przeczytać. Sam używam tego jako części UISwitch, która przełącza subview z parą UITextField s z prostą i subtelną animacją zwijania(0.2 sekundy). Ograniczenia dla subview są obsługiwane w podklasach UIView metod updateConstraints, jak opisano powyżej.

 98
Author: Cameron Lowell Palmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 09:27:50

Ogólnie rzecz biorąc, wystarczy zaktualizować ograniczenia i wywołać layoutIfNeeded wewnątrz bloku animacji. Może to być zmiana właściwości .constant NSLayoutConstraint, dodanie Usuń ograniczenia (iOS 7) lub zmiana właściwości .active ograniczeń (iOS 8 i 9).

Przykładowy Kod:

[UIView animateWithDuration:0.3 animations:^{
    // Move to right
    self.leadingConstraint.active = false;
    self.trailingConstraint.active = true;

    // Move to bottom
    self.topConstraint.active = false;
    self.bottomConstraint.active = true;

    // Make the animation happen
    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}];

Przykładowa Konfiguracja:

Projekt Xcode więc przykładowy projekt animacji.

Kontrowersje

Są pytania, czy ograniczenie powinno zostać zmienione przed blok animacji, lub wewnątrz to (patrz poprzednie odpowiedzi).

Poniżej znajduje się rozmowa na Twitterze między Martinem Pilkingtonem, który uczy iOS, a Kenem Ferrym, który napisał Układ Auto. Ken wyjaśnia, że chociaż zmiana stałych poza blokiem animacji może obecnie działać, nie jest to bezpieczne i naprawdę należy je zmienić wewnątrz animacja blok. https://twitter.com/kongtomorrow/status/440627401018466305

Animacja:

Przykładowy Projekt

Oto prosty projekt pokazujący, jak można animować widok. Korzysta z Objective C i animuje widok zmieniając właściwość .active kilku ograniczeń. https://github.com/shepting/SampleAutoLayoutAnimation

 60
Author: Steven Hepting,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-13 00:52:08
// Step 1, update your constraint
self.myOutletToConstraint.constant = 50; // New height (for example)

// Step 2, trigger animation
[UIView animateWithDuration:2.0 animations:^{

    // Step 3, call layoutIfNeeded on your animated view's parent
    [self.view layoutIfNeeded];
}];
 32
Author: John Erck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-23 14:29:37

Storyboard, Kod, porady i kilka Gotchas

Inne odpowiedzi są po prostu w porządku, ale ta podkreśla kilka dość ważnych gotchas animowania ograniczeń za pomocą niedawnego przykładu. Przeszedłem przez wiele odmian, zanim zdałem sobie sprawę, że:

Utwórz ograniczenia, które chcesz przypisać do zmiennych klasy, aby zawierały silne odniesienie. W Swifcie użyłem zmiennych lazy:

lazy var centerYInflection:NSLayoutConstraint = {
       let temp =  self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
        return temp!
}()

Po kilku eksperymentach zauważyłem, że trzeba uzyskać ograniczenie z widok powyżej (aka superview) dwa widoki, w których ograniczenie jest zdefiniowane. W poniższym przykładzie (zarówno MNGStarRating, jak i UIWebView są dwoma typami elementów, między którymi tworzę ograniczenie, i są one podwidaniami wewnątrz siebie.widok).

Łańcuchowanie Filtrów

Korzystam z metody filtrowania Swifta, aby oddzielić pożądane ograniczenie, które będzie służyć jako punkt przegięcia. Można również uzyskać znacznie bardziej skomplikowane, ale filtr robi dobrą robotę proszę.

Animowanie Ograniczeń Za Pomocą Swift

Nota Bene-ten przykład jest rozwiązaniem storyboard / code i zakłada jeden wprowadził domyślne ograniczenia w storyboardzie. Można wtedy Animuj zmiany za pomocą kodu.

Zakładając, że utworzysz właściwość filtrującą z dokładnymi kryteriami i dotrzesz do określonego punktu przegięcia dla animacji (oczywiście możesz również filtrować dla tablicy i pętli, jeśli potrzebujesz wielu ograniczenia):

lazy var centerYInflection:NSLayoutConstraint = {
    let temp =  self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
    return temp!
}()

....

Jakiś czas później...

@IBAction func toggleRatingView (sender:AnyObject){

    let aPointAboveScene = -(max(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height) * 2.0)

    self.view.layoutIfNeeded()


    //Use any animation you want, I like the bounce in springVelocity...
    UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.75, options: [.CurveEaseOut], animations: { () -> Void in

        //I use the frames to determine if the view is on-screen
        if CGRectContainsRect(self.view.frame, self.ratingView.frame) {

            //in frame ~ animate away
            //I play a sound to give the animation some life

            self.centerYInflection.constant = aPointAboveScene
            self.centerYInflection.priority = UILayoutPriority(950)

        } else {

            //I play a different sound just to keep the user engaged
            //out of frame ~ animate into scene
            self.centerYInflection.constant = 0
            self.centerYInflection.priority = UILayoutPriority(950)
            self.view.setNeedsLayout()
            self.view.layoutIfNeeded()
         }) { (success) -> Void in

            //do something else

        }
    }
}

The many wrong turns

Te notatki są naprawdę zestawem wskazówek, które napisałem dla siebie. Zrobiłem wszystkie zakazy osobiście i boleśnie. Mam nadzieję, że ten przewodnik oszczędzi innych.

  1. Uważaj na zPositioning. Czasami, gdy nic nie jest pozornie dzieje się, należy ukryć niektóre z innych widoków lub użyć widoku debugger do zlokalizowania animowanego widoku. Znalazłem nawet przypadki, w których Tryb Runtime Zdefiniowany Przez Użytkownika Atrybut został utracony w storyboardzie xml i doprowadził do animowanego widok jest zakryty (podczas pracy).

  2. Zawsze poświęć chwilę na przeczytanie dokumentacji (nowej i starej), szybko Pomoc i nagłówki. Apple ciągle wprowadza wiele zmian na lepsze Zarządzaj ograniczeniami AutoLayout(zobacz widoki stosu). Albo przynajmniej AutoLayout Cookbook . Pamiętaj, że czasami najlepsze rozwiązania znajdują się w starszej dokumentacji/filmach.

  3. Play around z wartościami w animacji i rozważ użycie inne warianty animacji.

  4. Nie koduj na twardo określonych wartości układu jako kryteriów określania zmiany na inne stałe, zamiast tego użyj wartości, które pozwalają określ lokalizację widoku. CGRectContainsRect jest jednym przykład

  5. W razie potrzeby, nie wahaj się użyć marginesów układu związanych z widok uczestniczący w definicji ograniczenia let viewMargins = self.webview.layoutMarginsGuide: jest na przykładzie
  6. Don 't do work you don' t have do zrobienia, wszystkie widoki z ograniczeniami na storyboard mają ograniczenia związane z nieruchomością siebie.viewName.ograniczenia
  7. zmień swoje priorytety dla wszelkich ograniczeń na mniej niż 1000. I set jeśli chcesz zmienić priorytet 1000 na cokolwiek w kodzie, aplikacja zawiesi się, ponieważ 1000 jest wymagane)
  8. nie należy od razu próbować używać activateConstraints i deactivateConstraints (mają swoje miejsce, ale kiedy tylko uczenie się lub jeśli używasz storyboardu za pomocą tych prawdopodobnie oznacza, że robisz zbyt wiele ~ mają miejsce, jak widać poniżej) {]}
  9. rozważ, że nie używasz addConstraints / removeConstraints, chyba że naprawdę dodanie nowego ograniczenia w kodzie. I found that most times I układanie widoków w storyboardzie z pożądanymi ograniczeniami (umieszczanie widok poza ekranem), a następnie w kodzie animuję ograniczenia wcześniej utworzone w storyboardzie, aby przesunąć widok.
  10. spędziłem dużo zmarnowanego czasu na budowanie nowych Klasa i podklasa NSAnchorLayout. Te działają dobrze, ale to Zajęło mi trochę czasu, aby zdać sobie sprawę, że wszystkie ograniczenia, które potrzebne już istniał w storyboardzie. Jeśli budujesz ograniczenia w kodzie następnie z pewnością użyj tej metody, aby połączyć swoje ograniczenia: {]}

Szybkie próbki rozwiązań, których należy unikać przy użyciu Storyboardów

private var _nc:[NSLayoutConstraint] = []
    lazy var newConstraints:[NSLayoutConstraint] = {

        if !(self._nc.isEmpty) {
            return self._nc
        }

        let viewMargins = self.webview.layoutMarginsGuide
        let minimumScreenWidth = min(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height)

        let centerY = self.ratingView.centerYAnchor.constraintEqualToAnchor(self.webview.centerYAnchor)
        centerY.constant = -1000.0
        centerY.priority = (950)
        let centerX =  self.ratingView.centerXAnchor.constraintEqualToAnchor(self.webview.centerXAnchor)
        centerX.priority = (950)

        if let buttonConstraints = self.originalRatingViewConstraints?.filter({

            ($0.firstItem is UIButton || $0.secondItem is UIButton )
        }) {
            self._nc.appendContentsOf(buttonConstraints)

        }

        self._nc.append( centerY)
        self._nc.append( centerX)

        self._nc.append (self.ratingView.leadingAnchor.constraintEqualToAnchor(viewMargins.leadingAnchor, constant: 10.0))
        self._nc.append (self.ratingView.trailingAnchor.constraintEqualToAnchor(viewMargins.trailingAnchor, constant: 10.0))
        self._nc.append (self.ratingView.widthAnchor.constraintEqualToConstant((minimumScreenWidth - 20.0)))
        self._nc.append (self.ratingView.heightAnchor.constraintEqualToConstant(200.0))

        return self._nc
    }()

Jeśli zapomnisz jednej z tych wskazówek lub tych bardziej prostych, takich jak gdzie dodać layoutIfNeeded, najprawdopodobniej nic się nie stanie: w takim przypadku możesz mieć na wpół upieczone rozwiązanie takie jak to:

NB-poświęć chwilę, aby przeczytać sekcję AutoLayout poniżej i oryginalny poradnik. Istnieje sposób wykorzystania tych technik w celu uzupełnienia twoi dynamiczni animatorzy.

UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 1.0, options: [.CurveEaseOut], animations: { () -> Void in

            //
            if self.starTopInflectionPoint.constant < 0  {
                //-3000
                //offscreen
                self.starTopInflectionPoint.constant = self.navigationController?.navigationBar.bounds.height ?? 0
                self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)

            } else {

                self.starTopInflectionPoint.constant = -3000
                 self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
            }

        }) { (success) -> Void in

            //do something else
        }

    }

Fragment z przewodnika AutoLayout (Uwaga drugi fragment dotyczy OS X). BTW-tego już nie ma w aktualnym poradniku z tego co widzę. The preferowane techniki nadal ewoluują.

Animowanie zmian wprowadzonych przez Auto Layout

Jeśli potrzebujesz pełnej kontroli nad animowanymi zmianami wprowadzanymi przez układ Automatyczny, musisz programowo wprowadzać zmiany ograniczeń. Podstawowa koncepcja jest taka sama zarówno dla iOS, jak i OS X, ale istnieje kilka drobnych różnic.

W aplikacji na iOS Twój kod będzie wyglądał mniej więcej tak:

[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
     // Make all constraint changes here
     [containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];

W systemie OS X użyj poniższego kodu, gdy używasz warstwy animacje:

[containterView layoutSubtreeIfNeeded];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
     [context setAllowsImplicitAnimation: YES];
     // Make all constraint changes here
     [containerView layoutSubtreeIfNeeded];
}];

Jeśli nie używasz animacji opartych na warstwach, musisz animować stałą za pomocą animatora ograniczenia:

[[constraint animator] setConstant:42];

Dla tych, którzy uczą się lepiej wizualnie sprawdź ten wczesny film od Apple .

Zwróć Szczególną Uwagę

Często w dokumentacji są małe notatki lub fragmenty kodu, które prowadzą do większych pomysłów. Na przykład dołączanie ograniczeń układu automatycznego do dynamicznych animatorów to świetny pomysł.

Powodzenia i Niech Moc będzie z Tobą.

 11
Author: Tommie C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-02 00:44:32

Swift 4 solution

UIView.animate

Trzy proste kroki:

  1. Zmień ograniczenia, np.:

    heightAnchor.constant = 50
    
  2. Powiedz view, że jego układ jest brudny i że autolayout powinien ponownie obliczyć układ:

    self.view.setNeedsLayout()
    
  3. W bloku animacji Poleć układowi przeliczanie układu, co jest równoznaczne z bezpośrednim ustawieniem klatek (w tym przypadku autolayout ustawi ramki):

    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
    }
    

Kompletny najprostszy przykład:

heightAnchor.constant = 50
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.5) {
    self.view.layoutIfNeeded()
}

Sidenote

Istnieje opcjonalny krok 0 - przed zmianą ograniczeń możesz wywołać self.view.layoutIfNeeded(), aby upewnić się, że punkt wyjścia dla animacji jest ze stanu ze starymi ograniczeniami (w przypadku, gdy były inne ograniczenia, które nie powinny być zawarte w animacji):

otherConstraint.constant = 30
// this will make sure that otherConstraint won't be animated but will take effect immediately
self.view.layoutIfNeeded()

heightAnchor.constant = 50
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.5) {
    self.view.layoutIfNeeded()
}

UIViewPropertyAnimator

Od z iOS 10 mamy nowy mechanizm animacji - UIViewPropertyAnimator, powinniśmy wiedzieć, że zasadniczo ten sam mechanizm dotyczy go. Kroki są w zasadzie takie same:

heightAnchor.constant = 50
self.view.setNeedsLayout()
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: UICubicTimingParameters(animationCurve: .linear))
animator.addAnimations {
    self.view.layoutIfNeeded()
}
animator.startAnimation()

Ponieważ animator jest enkapsulacją animacji, możemy zachować odniesienie do niej i nazwać ją później. Ponieważ jednak w bloku animacji po prostu mówimy autolayout, aby przeliczał klatki, musimy zmienić ograniczenia przed wywołaniem startAnimation. Dlatego coś takiego jest możliwe:

// prepare the animator first and keep a reference to it
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: UICubicTimingParameters(animationCurve: .linear))
animator.addAnimations {
    self.view.layoutIfNeeded()
}

// at some other point in time we change the constraints and call the animator
heightAnchor.constant = 50
self.view.setNeedsLayout()
animator.startAnimation()

Kolejność zmiana ograniczeń i uruchomienie animatora jest ważne - jeśli tylko zmienimy ograniczenia i zostawimy nasz animator na jakiś późniejszy punkt, następny cykl przerysowania może wywołać ponowne przeliczenie autolayout i zmiana nie będzie animowana.

Pamiętaj również, że pojedynczy animator nie nadaje się do wielokrotnego użytku - po jego uruchomieniu nie można go "ponownie uruchomić". Myślę więc, że nie ma dobrego powodu, aby trzymać animatora w pobliżu, chyba że użyjemy go do sterowania interaktywną animacją.

 8
Author: Milan Nosáľ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 11:09:32

Szybkie rozwiązanie:

yourConstraint.constant = 50
UIView.animateWithDuration(1, animations: yourView.layoutIfNeeded)
 6
Author: Nazariy Vlizlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 08:42:41

Rozwiązanie Robocze 100% Swift 3.1

Przeczytałem wszystkie odpowiedzi i chcę udostępnić kod i hierarchię linii, które wykorzystałem we wszystkich moich aplikacjach do ich poprawnego animowania, niektóre rozwiązania tutaj nie działają, należy je sprawdzić na wolniejszych urządzeniach, np. iPhone 5 w tym momencie.

self.view.layoutIfNeeded() // Force lays of all subviews on root view
UIView.animate(withDuration: 0.5) { [weak self] in // allowing to ARC to deallocate it properly
       self?.tbConstraint.constant = 158 // my constraint constant change
       self?.view.layoutIfNeeded() // Force lays of all subviews on root view again.
}
 5
Author: C0mrade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-12 08:41:17

Próbowałem animować ograniczenia i nie było łatwo znaleźć dobre wyjaśnienie.

To, co mówią inne odpowiedzi, jest całkowicie prawdziwe: musisz zadzwonić [self.view layoutIfNeeded]; do środka animateWithDuration: animations:. Jednak Innym ważnym punktem jest posiadanie wskaźników dla każdego NSLayoutConstraint, który chcesz animować.

Stworzyłem przykład w GitHub .

 4
Author: Gabriel.Massana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-23 08:49:38

Działa i właśnie Przetestowane rozwiązanie dla Swift 3 z Xcode 8.3.3:

self.view.layoutIfNeeded()
self.calendarViewHeight.constant = 56.0

UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)

Po prostu miej to na uwadze.calendarViewHeight to ograniczenie, o którym mowa w widoku niestandardowym (CalendarView). Dzwoniłem .layoutIfNeeded () on self.widok, a nie na siebie.calendarView

Mam nadzieję, że to pomoże.
 3
Author: Edoardo Vicoli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 12:17:43

Jest artykuł mówiący o tym: http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was

W którym zakodował tak:

- (void)handleTapFrom:(UIGestureRecognizer *)gesture {
    if (_isVisible) {
        _isVisible = NO;
        self.topConstraint.constant = -44.;    // 1
        [self.navbar setNeedsUpdateConstraints];  // 2
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded]; // 3
        }];
    } else {
        _isVisible = YES;
        self.topConstraint.constant = 0.;
        [self.navbar setNeedsUpdateConstraints];
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded];
        }];
    }
}
Mam nadzieję, że to pomoże.
 2
Author: D.D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-13 08:35:13

W kontekście animacji ograniczeń chciałbym wspomnieć o konkretnej sytuacji, w której animowałem ograniczenie natychmiast w powiadomieniu keyboard_opened.

Ograniczenie definiowało górną przestrzeń od pola tekstowego do górnej części kontenera. Po otwarciu klawiatury dzielę stałą przez 2.

Nie udało mi się uzyskać spójnej, płynnej animacji ograniczenia bezpośrednio w powiadomieniu klawiatury. Mniej więcej połowa widoku przeskoczyłaby do nowej pozycji - bez animacji.

Wydawało mi się, że w wyniku otwarcia klawiatury może wystąpić jakiś dodatkowy layouting. Dodanie prostego bloku dispatch_after z opóźnieniem 10ms sprawiło, że animacja była uruchamiana za każdym razem - bez skoków.

 1
Author: ivanferdelja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-15 15:54:27

Dla innych Xamarian, Oto Xamarin.wersja iOS / C#:

UIView.Animate(5, () =>
{
    _addBannerDistanceFromBottomConstraint.Constant = 0;
    View.LayoutIfNeeded();
});
 0
Author: Martin Zikmund,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-03 08:46:51