Анимации не работают должным образом

Я модально представляю контроллер представления в своем приложении. Я бы хотел, чтобы пользователь мог жестом «отбрасывать» вид. Я написал код ниже для этого:

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    CGFloat elasticThreshold = 100;
    CGFloat dismissThreshold = 200;
    CGPoint translation = [recognizer translationInView:self.view];
    CGFloat newY = 0;
    CGFloat translationFactor = 0.5;

    if (recognizer.state == UIGestureRecognizerStateEnded) {
        if (translation.y < dismissThreshold) {
            newY = 0;
        }
    } else {
        if (translation.y > elasticThreshold) {
            CGFloat frictionLength = translation.y - elasticThreshold;
            CGFloat frictionTranslation = 30 * atan(frictionLength/120) + frictionLength/10;
            newY = frictionTranslation + (elasticThreshold * translationFactor);
        } else {
            newY = translation.y*translationFactor;
        }
    }

    if (translation.y > dismissThreshold) {
        [UIView animateKeyframesWithDuration:0.5 delay:0.0 options:0 animations:^{
            [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
                self.overlay.effect = nil;
                self.collectionView.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height);
            }];
            [UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.1 animations:^{
                self.pageControl.frame = CGRectMake((self.view.frame.size.width-200)/2, self.view.frame.size.height, 200, 20);
            }];
        } completion:^(BOOL finished) {
            if (finished) {
                [self dismissViewControllerAnimated:YES completion:nil];
            }
        }];
    } else {
        self.collectionView.transform = CGAffineTransformMakeTranslation(0, newY);
        self.pageControl.transform = CGAffineTransformMakeTranslation(0, (newY+self.collectionView.frame.size.height)-20);
    }
}

Это подключено к UIGestureRecognizer:

self.pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
self.pan.delegate = self;
self.pan.maximumNumberOfTouches = 1;
[self.view addGestureRecognizer:self.pan];

Однако происходит то, что блок завершения выполняется немедленно. Таким образом, вы увидите, как изображение перемещается вниз (из-за dismissViewControllerAnimated) и в то же время видите, что overlay.effect уходит. Однако я бы хотел, чтобы мои анимации происходили, а затем чтобы контроллер представления молча закрывал себя.

Есть идеи, что здесь не так?


person user4992124    schedule 12.09.2017    source источник
comment
что происходит с остальной обработкой жестов? Вы перемещаете вид при изменении состояния жеста? Кажется странным делать что-либо только тогда, когда кастрюля закончилась.   -  person jrturton    schedule 12.09.2017
comment
Я возвращаю его к 0, когда панорама заканчивается. В противном случае я перемещаю вид вниз, да.   -  person user4992124    schedule 12.09.2017
comment
но этот код не в вашем вопросе   -  person jrturton    schedule 12.09.2017
comment
О, извините, я неправильно понял, оператор if применяется только к первой части кода. Обычно чище использовать переключатель для состояния жеста в коде обработки :)   -  person jrturton    schedule 12.09.2017


Ответы (2)


Это происходит потому, что вы вкладываете UIView блоков анимации. Вы должны использовать dispatch_after для этого:

double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self dismissViewControllerAnimated:YES completion:nil];
});
person Tamás Sengel    schedule 12.09.2017
comment
Я не гнездюсь? Я просто добавляю ключевые кадры в animateKeyframesWithDuration. Но отсрочка увольнения контроллера представления может сработать, да. - person user4992124; 12.09.2017
comment
@user4992124 user4992124 Дело в том, что вы вызываете блоки внутри основного блока, и это запускает блок завершения раньше, чем ожидалось. - person Tamás Sengel; 12.09.2017
comment
Это по-прежнему приводит к тому, что представление закрывается почти мгновенно. - person user4992124; 12.09.2017
comment
Это не проблема и не хорошее решение проблемы. - person jrturton; 12.09.2017

Анимация ключевого кадра UIView (или стандартная) немедленно выполнит свой блок завершения, если нет никакой работы. Он не будет ждать окончания анимации, если анимировать нечего.

Кажется, что в вашем случае, когда вы запускаете анимацию отклонения, представления уже находятся в своем конечном состоянии, поэтому анимации нет, и блок завершения запускается немедленно.

person jrturton    schedule 12.09.2017