15

我有一个 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。UIScrollView 的同级 UIToolbar 不响应触摸事件,作为 UIScrollView 同级的子视图的其他按钮也不响应。似乎整个父 UIView在动画进行时被冻结在用户交互之外。同样,在动画完成后,上述所有 UIView 都会再次响应。

这些都在 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 将被弃用然后消失,我宁愿朝着一个持久的方向前进。

非常感谢您的关注。

4

2 回答 2

45

您只需要在调用动画时包含 UIViewAnimationOptionAllowUserInteraction 选项,如下所示:

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

这是一个偷偷摸摸的,我知道!;)

回复:“不鼓励”标签 - 一般来说,当 Apple 告诉您不要在设计在其平台上运行的应用程序方面做某事时,通常是为了您自己好。所以你想采用动画块而不是笨拙的旧方式是正确的。

于 2010-10-05T10:41:51.653 回答
2

quickthyme的答案是正确的。这是 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    
    }
)
于 2018-09-26T13:48:50.280 回答