动画期间的 UIScrollView 触摸事件不会使用 animateWithDuration: 触发,但可以与 UIView beginAnimations 一起正常工作:
我有一个 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;
所以,问题:我应该 - 忽略苹果的不鼓励 标签并继续使用 beginAnimation 公式?我应该使用 hitTest 重新实现缩放和其他基于触摸的事件吗?是否有一些关于动画块之间实现差异的知识可以帮助我解决这个问题?我是否缺少一些明显的东西?
我是 Apple 的新开发者,所以我不知道如何认真对待他们的不鼓励标签。但如果这个 API 将被弃用然后消失,我宁愿朝着持久的方向发展。
非常感谢您的关注。
I have a UIScrollView subclass that I am programmatically scrolling using UIView animations.
I'd like the user to be able to tap or zoom into the UIImageView content of the Scroll View while the animation is taking place.
This has worked fine while using a formulation akin to this:
- (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];
}
Now, since iOS 4.0, UIView beginAnimations: is discouraged. So I tried to update my code using a block and UIView animateWithDuration: The scrolling works identically to the above.
The key and maddening difference is that during animation, the UIScrollView and other views no-longer respond to event handling methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
Nor does :
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
get called when trying to zoom.
Edit for clarity : No UIView present responds to touch events. This isn't limited to just the UIScrollView. The UIScrollView's peer a UIToolbar does not respond to touch events, nor do other buttons that are subviews of a peer to the UIScrollView. It appears that the entire parent UIView is frozen out of user interaction while the animation is going on. Again, after the animation completes, all of the above UIViews are again responsive.
These all do get called in the UIView beginAnimations: formulation regardless of animation state.
My animateWithDuration: code is slightly different - but the differences are not material. As soon as the animation completes, the above touch events are again called...
here's my animate code:
- (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];
}
}
}];
}
The only event handler that fires during the above animation block is:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
So, question: Should I - ignore Apple's discouraged label and continue to use the beginAnimation formulation? Should I - reimplement zooming and my other touch-based events using hitTest? Is there some knowledge of the difference in implementation between animation blocks that can help me confront this problem? Is there something obvious that I'm missing?
I am a new developer to Apple, and so I don't know how seriously to take their discouraged tag. But if this API will be deprecated then disappear, I'd rather move in a lasting direction.
thanks so much for your attention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您只需要在调用动画时包含 UIViewAnimationOptionAllowUserInteraction 选项,如下所示:
我知道,这是一个偷偷摸摸的选择! ;)
回复:“不鼓励”标签 - 一般来说,当苹果告诉你不要做一些关于设计在其平台上运行的应用程序时,通常是为了你好。所以你想要采用动画块而不是笨重的旧方法是正确的。
You just need to include the UIViewAnimationOptionAllowUserInteraction option when invoking the animation like so:
That's a sneaky one, I know! ;)
Re: The "Discouraged" tag - In general, when Apple tells you not to do something in regards to designing applications that run on their platforms, it's usually for your own good. So you are right in wanting to adopt animation blocks instead of the clunky old way.
quickthyme
的答案是正确的。 中的片段这是 Swift Swift 4
quickthyme
's answer is correct. Here is the snippet in SwiftSwift 4