Подтвердить что ты не робот

Различия в различиях анимации ограничений AutoLayout в iOS 10?

Я заметил, что в iOS 10 Beta 5 (собирается попробовать Beta 6) анимация ограничений AutoLayout ведет себя по-другому.

Например, этот подход не работает так же, как в предыдущих версиях iOS:

[view addConstraints:@[constraints...]];

[view setNeedsUpdateConstraints];
[view layoutIfNeeded];

[UIView animateWithDuration:...
{
    /* adjust constraint here... */
    [view layoutIfNeeded]; // Only the adjusted constraints since previous layoutIfNeeded() call should animate change with duration.

} completion:{ ... }];

... В моем тестировании ограничения, первоначально добавленные с помощью addConstraints(), будут также анимировать в iOS 10 с блоком UIView animateWithDuration()..., что вызывает некоторое вредное/нежелательное поведение, поэтому далеко.

Например, установка ограничений влево/вправо в массиве (но вертикальные ограничения в блоке) заставляет весь вид анимировать на экране по диагонали с помощью этого подхода... который полностью неверно.

Кто-нибудь знает, как сделать это правильно как для iOS 9 (и ниже), так и для 10?

4b9b3361

Ответ 1

Попробуйте вызвать layoutIfNeeded в представлении view, а не в самом представлении.

-

У меня была аналогичная проблема, мой взгляд должен был анимироваться сверху с высоты 0, вниз до высоты > 0 (т.е. (0, 0, 320, 0) до (0, 0, 320, 44)).

Используя Xcode 8 с iOS 10, поведение анимации было сильно иным. Вместо того, чтобы анимировать вниз сверху, представление анимируется вверх и вниз от вертикального центра кадра назначения.

Я исправил это, вместо того, чтобы называть layoutIfNeeded на самом представлении, вызывая его в представлении viewview. Каким-то образом поведение было восстановлено.

Надеюсь, что это поможет!


Полезный комментарий от @Ramiro:

В соответствии с документацией layoutIfNeeded излагает subviews (но не рассматривает текущее представление). Итак, чтобы обновить текущее представление, вы должны вызвать layoutIfNeeded из супер-представления.

Ответ 2

В приведенном ниже методе:

[super viewDidLoad];

Запишите эту строку:

 [self.view layoutIfNeeded];

Ответ 3

Я сделал небольшой тест, изменяя H и V небольшого красного вида:

self.red_POS_H = NSLayoutConstraint.constraints(withVisualFormat: "H:|-90-[redView]", options: defaultOptions, metrics: nil, views: viewsDictionary)


self.red_POS_V = NSLayoutConstraint.constraints(withVisualFormat: "V:|-30-[redView]", options: defaultOptions, metrics: nil, views: viewsDictionary)

self.view.addConstraints(self.red_POS_V!)
self.view.addConstraints(self.red_POS_H!)

и оживить его:

        // we hope is only one:
        let currV = self.red_POS_V![0]
        let currH = self.red_POS_H![0]


        UIView.animate(withDuration: 3) { 
            // Make all constraint changes here

            currV.constant = 100
            currH.constant = 300

            self.view.layoutIfNeeded() // Forces the layout of the subtree animation block and then captures all of the frame changes
        }

красный вид перемещен правильно, если вы прокомментируете одиночную строку в анимации, она работает, по горизонтали или по вертикали.

Малый проект доступен, если вам это нужно.