在动画 UIView/CALayer 中处理触摸的最佳模式?
Posted
技术标签:
【中文标题】在动画 UIView/CALayer 中处理触摸的最佳模式?【英文标题】:Best pattern for handling touches in an animated UIView/CALayer? 【发布时间】:2012-02-16 04:35:35 【问题描述】:我有一个 UIView
实例,我正在使用 CAKeyframeAnimation
制作动画。这是一个循环动画,将不断运动。但是,我需要允许用户与该项目进行交互(准确地说是响应点击)。因为 CoreAnimation 只移动表示层而不是模型,所以我不能使用 UIButton
实例来获取 touchUpInside
事件。
考虑以下基本示例布局:
我通过覆盖UIView
子类上的touchesEnded:withEvent:
方法将蓝色框用于触摸事件。然后我通过NSNotification
(我真的不想引入很多耦合来处理这个事件)将该事件冒泡到包含的视图控制器,然后在红色框上执行hitTest:
动画。
仅仅能够触摸动画UIView
,所有这一切似乎都相当骇人听闻。 处理动画UIView
/CALayer
实例的触摸的最佳模式是什么?
【问题讨论】:
必须使用 CA 吗? CA 最适合平滑动画,因为它是轻量级的,而且它是轻量级的,因为它没有所有事件处理的东西(部分正确)。如果您以某种方式为其添加事件处理,那么您可能会破坏流畅的 GPU 能力。我不确定有没有办法解决这个问题。它需要有多光滑?您可能希望使用其他一些实际使用 CPU 移动模型的动画技术来制作动画。只是和你一起大声思考。 @Vinnie - 问题是这个例子是一个非常简单的动画。真正的问题实际上涉及几个关键帧来为沿路径的视图设置动画,以及在沿路径移动时进行一些旋转。动画还需要无限重复,所以使用基于块的 UIView 确实不太合适。 【参考方案1】:我相信在超级视图中跟踪触摸是正确的。但我会在超级视图中进行命中测试,而不是向视图控制器发布通知。像这样的:
创建一个MYAnimationContainerView
类(蓝色框)。
给它一个拥有视图控制器设置的委托或块回调。例如:
__weak id weakSelf = self;
MYAnimationContainerView *view = [[MYAnimationContainerView alloc] initWithTouchCallback:^(UIView *touchedView)
[weakSelf handleTouchToView:touchedView];
];
在MYAnimationContainerView
中,同时覆盖touchesBegan:withEvent:
和touchesEnded:withEvent:
。在began
中,对移动视图的表示层执行命中测试。跟踪哪一个(如果有的话)被触摸了。在ended
中,执行另一个命中测试。如果是相同的视图,则调用您的回调。
上面可以很容易地用delegate
协议而不是一个块来实现。我刚刚养成了喜欢块而不是单一方法委托协议的习惯。
您也可以使用目标/选择器来实现它,但该模式已成为a bit of a hassle with ARC,我倾向于不鼓励今天使用它。
【讨论】:
我更喜欢你的方法。谢谢!【参考方案2】:如果你想在视图中处理特定对象的触摸,比如蓝色的红色框,最好创建一个单独的类,比如 UIview 的子类,并在其中处理触摸事件。它干净而抽象。
在许多这样的对象的情况下,触摸事件由它自己处理。
我不确定这是否符合您的预期。
【讨论】:
触摸不是自己处理的,这是因为只有表现层是动画的,模型层是处理触摸的。以上是关于在动画 UIView/CALayer 中处理触摸的最佳模式?的主要内容,如果未能解决你的问题,请参考以下文章