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

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

问题描述:

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

I'm trying to make an exact "translation" of this UIView block-based animation code:

[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 ,它适用于那个视图。

I'm totally aware that the frame property is actually a combination of position, bounds and anchorPoint of the underlying layer, as it is described here: http://developer.apple.com/library/mac/#qa/qa1620/_index.html
... and I already made a solution like that, using two CABasicAnimations one setting the position, one for bounds and it works for that one view.

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

The problem is however that I have subviews inside my view. someView has a subview of type UIScrollView in which I place still another subview of type UIImageView. UIScrollView subview has autoresizingMask set to UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight. That all works perfectly if I use the UIView block-based version, however when I try using CABasicAnimations the subviews start behaving unexpectedly(i.e. get resized to incorrect widths). So it seems autoresizingMask is not working correctly when using CABasicAnimations. I noticed also that subviews don't receive a call to setFrame:, although the frame property of the parent view does change after changes to layer position and bounds are made.

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

That's why I would like to know what would be the correct code to replicate with CABasicAnimation that what is happening when one uses UIView's animateWithDuration method.


我完全清楚框架属性实际上是位置,边界和底层的anchorPoint

I'm totally aware that the frame property is actually a combination of position, bounds and anchorPoint of the underlying layer

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

Good, but it's important also to be aware that frame is not an animatable property for layers. If you want to animate with CABasicAnimation you must use properties that are animatable for layers. The CALayer documentation marks every such property as explicitly "animatable". The idea of using bounds and position is correct.

因此,此代码基本上与您之前所做的相同:

Thus, this code does essentially what you were doing before:

[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 的子图层绘制。)不幸的是,这是你的问题正试图解决。我相信通过降低到图层级别并直接显式核心动画,您已经放弃了自动调整,这在视图级别发生。因此,您还需要为子图层设置动画。这就是动画视图为你做的。

However, that code has no effect on the size of any sublayers of v.layer. (A subview of v is drawn by a sublayer of v.layer.) That, unfortunately, is the problem you are trying to solve. I believe that by dropping down to the level of layers and direct explicit core animation, you have given up autoresizing, which happens at the view level. Thus you will need to animate the sublayers as well. That is what view animation was doing for you.

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

This is an unfortunate feature of iOS. Mac OS X has layer constraints (CAConstraint) that do at the layer level what autoresizing does at the view level (and more). But iOS is missing that feature.