旋转没有动画的自定义 UIView

Posted

技术标签:

【中文标题】旋转没有动画的自定义 UIView【英文标题】:Rotating custom UIView with no animation 【发布时间】:2016-06-21 20:26:38 【问题描述】:

我在 drawRect 中绘制了一个罗盘刻度盘,我想避免重新绘制它,而是在航向罗盘航向变化时旋转它。当我像这样使用 CABasicAnimation 时:

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:_dialAngle*M_PI/180];
animation.toValue = [NSNumber numberWithFloat:dialAngle*M_PI/180];
animation.duration = 0.0;
animation.repeatCount = 0;
animation.removedOnCompletion = false;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[dial.layer addAnimation:animation forKey:@"transform.rotation.z"];

它按预期旋转(顶部的红色箭头和文字与指南针表盘的视图不同):

我真的不想制作动画,所以我使用了如下变体:

[dial.layer setValue:[NSNumber numberWithDouble: dialAngle*M_PI/180] forKeyPath:@"transform.rotation.z"];

或者:

dial.transform = CGAffineTransformMakeRotation(arrowAngle*M_PI/180);

或者:

CATransform3D t = CATransform3DIdentity;

dial.layer.transform = CATransform3DRotate(t, dialAngle*M_PI/180, 0.0, 0.0, 1.0);

它们都导致相同的倾斜结果:

此视图上不存在自动布局和约束。

我应该遗漏了一些东西,但我不知道它是什么。为了获得与动画相同的结果,我缺少什么?

另外,根据您的经验,我真的应该使用旋转变换来支持drawRect吗?在分析器中,我看到 drawRect 占用了相当多的 cpu 周期。当我使用转换时,我看不到“我的”cpu 周期,但是当我强烈旋转时,总 CPU 值几乎相同。

在你的帮助下驯服变形会很棒:)!

【问题讨论】:

【参考方案1】:

在将我的头撞到墙上并查看视图上的 .transform 值后,我发现问题在于在 layoutSubviews 中为视图设置 .frame。仅使用边界和中心时:

dial.bounds = self.bounds;
dial.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));

它适用于问题中提到的所有转换选项。

事实证明,如果您在视图上设置了非身份转换 (docs),则不应触摸框架。

但是,如果 transform 属性包含非身份转换,则 frame 属性的值是未定义的,不应修改。在这种情况下,您可以使用 center 属性重新定位视图,并使用 bounds 属性调整大小。

还要确保不要在其他任何地方使用转换后的视图的 .frame。我在 drawRect 中将它用作 .frame.size,当然必须将其更改为 .bounds.size。

【讨论】:

以上是关于旋转没有动画的自定义 UIView的主要内容,如果未能解决你的问题,请参考以下文章

使用drawrect自定义UIView动画

拆分不同颜色的自定义 UIView

动画边界更改时具有 CALayer 有线效果的自定义视图

动画边界更改时具有 CALayer 有线效果的自定义视图

来自 XIB 的自定义 UIView 加载具有巨大规模的子视图

何时在自定义 UIVIew 中添加 CAAnimation?