Изгледите на UIPageViewController скачат при преоразмеряване на суперизглед след плъзгане

Имам контролер за изглед, който добавя UIPageViewController към подизглед (нека го наречем „наслагване“) програмно. Тъй като всяка от страниците на контролера за изглед на страница има различна височина, добавих NSLayoutConstraint в подизгледа "overlay".

При всяко плъзгане изчислявам височината на предстоящия контролер за изглед и съответно преоразмерявам изгледа с наслагване:

- (void)resizeOverlayToBottomOf:(UIView *)element {

   // resize overlay in parent view controller so it shows the element
   float bottomOfElement = element.frame.origin.y + element.frame.size.height + 20;
   [self.parentViewController.overlayHeightConstraint setConstant:bottomOfElement];

   [self.parentViewController.overlayView setNeedsUpdateConstraints];
   [self.parentViewController.overlayView setNeedsLayout];
   [self.parentViewController.overlayView layoutIfNeeded];
}

Всичко работи според очакванията... докато не искам да променя размера на наслагването с анимация.
Обвих последните два реда от горния метод с блок за анимация:

[UIView animateWithDuration:0.25f animations:^{
   [self.parentViewController.overlayView setNeedsLayout];
   [self.parentViewController.overlayView layoutIfNeeded];
}];

След приключване на плъзгането височината на изгледа с наслагване се променя с анимация.

Проблемът е, че докато се възпроизвежда анимацията, съдържанието на контролера за изглед на страница се връща обратно на някое място извън екрана и се плъзга обратно. Опитах се да добавя ограничения, за да осигуря фиксирана ширина на съдържанието на контролера за изглед на страница, но изглежда нищо не върши работа.

Всеки намек за това как да анимирате изгледа родител, без да засягате изгледите на контролера за изглед на страница, ще бъде високо оценен!


person Nils Hott    schedule 06.05.2014    source източник
comment
Опитахте ли да преместите [self.parentViewController.overlayView setNeedsUpdateConstraints]; вътре в анимационния блок?   -  person user1459524    schedule 06.05.2014
comment
Да, опитах да го преместя в блока за анимация. Не помага.   -  person Nils Hott    schedule 06.05.2014


Отговори (2)


Наскоро имах същия проблем. Това очевидно работи:

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    if (completed)
    {
        CGFloat height = [self calculateHeight];
        [CATransaction begin];
        [CATransaction setCompletionBlock:^{
            self.heightConstraint.constant = height;
            [UIView animateWithDuration: 0.25
                                  delay: 0
                                options: UIViewAnimationOptionCurveEaseInOut
                             animations:^{

                                 [self.view layoutIfNeeded];
                             }
                             completion:^(BOOL finished) {

                             }];
        }];
        [CATransaction commit];
    }
}

Разбирам, че едната анимация пречи на другата.
CATransaction прихваща текущата анимация и ще направи нейния блок за завършване, след като текущата анимация е готова.
Това работи добре за мен.

person Board    schedule 25.09.2014
comment
Работи перфектно. - person Muhammad Hassan; 17.03.2018

Е, този код свърши работа:

[UIView animateWithDuration:0.25f animations:^{
    // [self.parentViewController.overlayView setNeedsLayout];
    // [self.parentViewController.overlayView layoutIfNeeded];
    CGRect frame = self.parentViewController.overlayView.frame;
    frame.size.height = bottomOfElement;
    self.parentViewController.overlayView.frame = frame;
}];

Смешното е, че изглежда няма значение каква стойност използвам за frame.size.height, ограничението изглежда е поставено в момента така или иначе.

Ако някой може да обясни защо това работи, ще се радвам.

person Nils Hott    schedule 06.05.2014