使用CABasicAnimation为框架属性设置动画

时间:2013-03-23 01:28:27

标签: ios objective-c core-animation

我正在尝试对此 UIView 基于块的动画代码进行精确的“翻译”:

[UIView animateWithDuration:0.5
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                               someView.frame = CGRect(0, 100, 200, 200);
                             }
                 completion:nil];

使用 CABasicAnimation 代替。

我完全清楚frame属性实际上是底层的 position bounds anchorPoint 的组合,因为它这里描述:http://developer.apple.com/library/mac/#qa/qa1620/_index.html
...我已经使用两个 CABasicAnimations 设置了位置,一个用于 bounds ,并且它适用于那个视图。

但问题是我在视图中有子视图。 someView有一个 UIScrollView 类型的子视图,其中我还放置了另一个类型为 UIImageView 的子视图。 UIScrollView 子视图将 autoresizingMask 设置为 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight 。如果我使用 UIView 基于块的版本,那一切都能正常工作,但是当我尝试使用 CABasicAnimations 时,子视图会出现意外行为(即调整大小不正确的宽度)。所以当使用 CABasicAnimations 时, autoresizingMask 似乎无法正常工作。我还注意到子视图没有接收到对 setFrame:的调用,尽管在更改图层位置和边界后父视图的frame属性确实发生了变化。

这就是为什么我想知道用 CABasicAnimation 复制的正确代码是什么,当使用UIView的 animateWithDuration 方法时会发生什么。

1 个答案:

答案 0 :(得分:11)

  

我完全清楚frame属性实际上是底层的position,bounds和anchorPoint的组合

很好,但同样重要的是要注意frame不是图层的可动画属性。如果要使用CABasicAnimation进行动画处理,则必须使用可为图层设置动画的属性。 CALayer文档将每个此类属性标记为显式“可动画”。使用boundsposition的想法是正确的。

因此,此代码基本上完成了您之前所做的事情:

[CATransaction setDisableActions:YES];
// set final bounds and position
v.layer.bounds = CGRectMake(0,0,200,200);
v.layer.position = CGPointMake(100,200);

// cause those changes to be animated
CABasicAnimation* a1 = [CABasicAnimation animationWithKeyPath:@"bounds"];
a1.duration = 0.5;
CABasicAnimation* a2 = [CABasicAnimation animationWithKeyPath:@"position"];
a2.duration = 0.5;
[v.layer addAnimation:a1 forKey:nil];
[v.layer addAnimation:a2 forKey:nil];

但是,该代码对v.layer的任何子图层的大小没有影响。 (v的子视图由v.layer的子图层绘制。)不幸的是,这是您要解决的问题。我相信通过降低到图层和直接显式核心动画的级别,您已经放弃了自动调整,这在视图级别发生。因此,您还需要为子图层设置动画。这就是动画视图为你做的。

这是iOS的一个不幸功能。 Mac OS X具有图层约束(CAConstraint),它在图层级别执行自动调整在视图级别执行的操作(以及更多)。但是iOS缺少这个功能。