События касания UIScrollView во время анимации не запускаются с animateWithDuration: но работают нормально с UIView beginAnimations: - PullRequest
14 голосов
/ 01 сентября 2010

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

Я бы хотел, чтобы пользователь мог касаться или увеличивать содержимое UIImageView представления прокрутки , пока анимация выполняется.

Это сработало нормально при использовании формулировки, похожей на эту:

- (void) scrollSmoothlyatPixelsPerSecond:(float)thePixelsPerSecond {
    // distance in pixels / speed in pixels per second
    float animationDuration = _scrollView.contentSize.width / thePixelsPerSecond;

    [UIView beginAnimations:@"scrollAnimation" context:nil];
    [UIView setAnimationCurve: UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:animationDuration];
    _scrollView.contentOffset = CGPointMake(_scrollView.contentSize.width, 0);
    [UIView commitAnimations];
}

Теперь, начиная с iOS 4.0, UIView beginAnimations: не рекомендуется. Поэтому я попытался обновить свой код, используя блок и UIView animateWithDuration: прокрутка работает так же, как и выше.

Ключевое и сводящее с ума отличие состоит в том, что во время анимации UIScrollView и другие представления больше не отвечают на методы обработки событий:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; 

Не делает:

-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;

вызывается при попытке увеличения.

Редактировать для ясности: UIView отсутствует, реагирует на сенсорные события. Это не ограничивается только UIScrollView. Одноранговый UITcolbar UIScrollView не реагирует на сенсорные события, равно как и другие кнопки, которые являются подпредставлениями однорангового узла UIScrollView. Похоже, что весь родительский UIView завис из-за взаимодействия с пользователем во время анимации . Опять же, после завершения анимации все вышеперечисленные UIViews снова реагируют.

Все они вызываются в UIView beginAnimations: формулировка независимо от состояния анимации.

Мой animateWithDuration: код немного отличается - но различия не существенны. Как только анимация завершается, вышеуказанные события касания снова называются ...

вот мой живой код:

- (void) scrollSmoothlyToSyncPoint:(SyncPoint *) theSyncPoint andContinue:(BOOL)theContinueFlag{

    float animationDuration = theSyncPoint.time - [player currentTime];
    [UIView animateWithDuration:animationDuration 
                          delay:0 
                        options:UIViewAnimationOptionCurveLinear 
                     animations:^{
        [_scrollView setContentOffset:theSyncPoint.contentOffset];
    } 
                     completion:^(BOOL finished){
                         if (theContinueFlag) {
                             SyncPoint *aSyncPoint = [self nextSyncPoint];
                             if (aSyncPoint) {
                                 [self scrollSmoothlyToSyncPoint:aSyncPoint andContinue:YES];
                             }
                         }
    }];
}

Единственный обработчик событий, который срабатывает во время вышеуказанного анимационного блока:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

Итак, вопрос: Должен ли я - игнорировать не одобренный Apple ярлык и продолжать использовать формулировку beginAnimation? Должен ли я - переопределить масштабирование и другие сенсорные события, используя hitTest? Есть ли какие-то знания о разнице в реализации между блоками анимации, которые могут помочь мне решить эту проблему? Есть ли что-то очевидное, чего мне не хватает?

Я новый разработчик для Apple, и поэтому я не знаю, насколько серьезно воспринимать их обескураженный тег . Но если этот API устареет, а затем исчезнет, ​​я бы предпочел двигаться в устойчивом направлении.

Большое спасибо за ваше внимание.

Ответы [ 2 ]

43 голосов
/ 05 октября 2010

Вам просто нужно включить опцию UIViewAnimationOptionAllowUserInteraction при вызове анимации следующим образом:

[UIView animateWithDuration:animationDuration 
                          delay:0 
                        options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
                     <snip>];

Это подлый, я знаю! ;)

Re: тег «Обескураженный» - в общем, когда Apple говорит вам не делать что-то в отношении разработки приложений, работающих на их платформах, это обычно для вашего же блага. Таким образом, вы правы в том, что хотите использовать анимационные блоки вместо старого неуклюжего.

0 голосов
/ 26 сентября 2018

quickthyme ответ правильный.Вот фрагмент в Swift

Swift 4

UIView.animate(
    withDuration: 0.3, // specify animation duration here 
    delay: 0, // specify delay if needed 
    options: [
        UIView.AnimationOptions.allowUserInteraction, 
        UIView.AnimationOptions.curveLinear
    ], 
    animations: {
        // animations code    
    }
)
...