如何在CABasicAnimation之后使UI对象响应 [英] How to make UI object responsive after CABasicAnimation

查看:119
本文介绍了如何在CABasicAnimation之后使UI对象响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在CABasicAnimation滑入和弹跳后尝试找到让我的UI对象(UISegmentedControl)触摸响应的方法。如何解决此问题?

I'm having trouble trying to find a way to make my UI object (UISegmentedControl) touch responsive after a CABasicAnimation slide in and bounce. How can I pull this off?

我知道移动后UI对象位于演示文稿树中。但是我真的很喜欢CABasicAnimation提供的setTimingFunction功能,我只是无法使用UIView动画获得如此平滑的反弹。

I know the UI object is in the presentation tree after the move. But I really like the setTimingFunction feature CABasicAnimation provides and I just won't be able to get such a smooth bounce using UIView animation.

动画示例GIF(循环播放):

Example GIF of animation (Looped):

代码我在viewDidLoad中使用

CABasicAnimation *startAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
[startAnimation setFromValue:[NSNumber numberWithFloat:0]];
[startAnimation setToValue:[NSNumber numberWithFloat:slidingUpValue]];
[startAnimation setDuration:1.0];
startAnimation.fillMode = kCAFillModeForwards;
startAnimation.removedOnCompletion = NO;
[startAnimation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:0.0 :0.0 :0.3 :1.8]];
[[gameTypeControl layer] addAnimation:startAnimation forKey:nil];


推荐答案

出了什么问题



问题是这两行代码而不理解使用它们的副作用:

What went wrong

The problem is these two lines of code and not understanding the side effects of using them:

startAnimation.fillMode = kCAFillModeForwards;
startAnimation.removedOnCompletion = NO;

第一行配置动画以在动画完成后继续显示结束值(你可以看到我的小作弊表中的fillMode和其他时序相关属性的可视化。

The first line configures the animation to keep showing the end value after the animation has completed (you can see a visualization of fillMode and the other timing related properties in my little cheat sheet).

第二行将动画配置为在完成后保持附加到图层。

The second line configures the animation to stay attached to the layer after it finishes.

这听起来很不错,但是缺少核心动画的重要组成部分:添加到图层的动画永远不会影响模型,只影响演示文稿核心动画编程指南在此提及核心动画基础知识部分的第二页

This sounds just fine at first, but is missing an essential part of Core Animation: animations added to a layer never affect the model, only the presentation. The Core Animation Programming Guide mention this on the second page of the section "Core Animation Basics":


图层对象的数据和状态信息与屏幕上该图层内容的可视化表示分离。

The data and state information of a layer object is decoupled from the visual presentation of that layer’s content onscreen.

动画发生在一个名为表示层的单独图层上,这是您在屏幕上看到的。如果在动画期间打印出动画属性的值,则它们根本不会更改。

Animations happen on a separate layer called the presentation layer which is what you see on screen. If you print out the values of the animated property during the animation they don't change at all.

在动画期间,你会在演示和模型之间产生差异,但动画可能很短,一旦动画结束,差异就会消失,所以它不会真的很重要......除非动画不会消失。然后差异持续存在,现在你必须处理两个地方的不同步数据。

During the animation you have a difference between the presentation and the model but the animation is probably short and that difference will go away as soon as the animation finishes, so it doesn't really matter... unless the animation doesn't go away. Then the difference has persisted and now you have to deal with having out-of-sync data in two places.

可以说看起来的一切都很好,只是命中测试是错误的。让补丁打击测试!更改命中测试以使用分段控件的图层表示层,命中测试将起作用。太棒了吧?这就像把一块石膏放在另一块上面而不是解决问题的原点。

One could say that everything looks good, it's just that hit testing is wrong. Let's patch hit testing! Change the hit testing to use the segment control's layer's presentation layer and hit testing will work. Great, right? This would be like putting one plaster on top of another instead of solving the problem at its origin.

这很简单:不要使用这些行并在完成后删除动画。有人可能会说苹果在幻灯片和示例代码中使用了这种技术(不删除动画),因此这是Apple推荐的,但有一个很容易错过的微妙细节:

It's really simple: don't use those lines and remove animations when they are finished. One might say that this technique (not removing an animation) has been used by Apple in slides and sample code so it's what Apple recommends, but there is a subtle detail that is easily missed:

当Apple在WWDC 2007上引入Core Animation时,他们使用这种技术来动画被删除的图层(例如,淡出)。以下引用来自会话211 - 将核心动画添加到您的应用程序:

When Apple introduced Core Animation at WWDC 2007 they used this technique to animate layers being removed (for example, fading out). Quote below is from Session 211 - Adding Core Animation to Your Application:



  • 要动态删除图层,请使用动画与

    fillMode = forwards,removedOnCompletion = NO


    • 动画代表可以删除图层

在这种情况下,它是完全没有删除动画,因为它可能导致图层在从图层层次结构中删除之前跳回到原始大小,不透明度等一帧。正如他们在上面的幻灯片中所说:动画委托可以删除图层(即:进行清理)。

In this case it's perfectly fine to not remove the animation since it could cause the layer to jump back to it's original size, opacity, etc. for one frame before being removed from the layer hierarchy. As they said in the above slide: the "animation delegate can remove the layer" (that is: do the clean up).

在其他情况下,没有人会进行清理工作,而且您会在两个地方(如上所述)处理不同步数据。(

In other cases no one does the clean up and you are left with the mess of having out of sync data in two places (as mentioned above).

构建动画时,我试着想到这样:

When building animations, I try to think of like this:


如果你的动画神秘地消失了,那么模型值应该是预期的最终状态。

If your animation mysteriously went away, the model value should be the expected end state.

应用于您的示例,分段控件正朝着它的最终位置移动,停在那里并留在那里。在这种情况下,分段控件的实际位置应该是结束位置。即使没有动画,应用程序也应该可以工作。

Applied to your example, the segmented control is moving towards it's final position to stop there and stay there. In that case the actual position of the segmented control should be the end position. The application should work even if the animation isn't there.

那么动画呢?不是将动画从0偏移动画到某个偏移,而是将其反转并从一些负偏移动画到0偏移。

So what about the animation? Instead of animating from 0 offset to some offset, you reverse that and animate from some negative offset to 0 offset.

CABasicAnimation *startAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
[startAnimation setFromValue:@(-slidingUpValue)]]; // these two changed 
[startAnimation setToValue:@(0.0)];                // places with each other
[startAnimation setDuration:1.0];
// no fill mode
// animation is removed on completion
[startAnimation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:0.0 :0.0 :0.3 :1.8]];
[[gameTypeControl layer] addAnimation:startAnimation forKey:@"Move in game type control from bottom"]; // I like adding descriptive keys for easier debugging

这篇关于如何在CABasicAnimation之后使UI对象响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆