0

进入 CALayer 世界:

我正在创建一个无论设备方向如何都需要保持在视图中间的层。有人可以告诉我为什么我的图层在从旧位置旋转后会动画,即使我将它从超级图层中移除?我知道 frame 和 borderWidth 属性是可动画的,但是即使从 superLayer 中删除它们也可以动画吗?

如果从 superLayer 中删除不会重置图层属性,因为图层对象尚未释放(好吧,我可以理解),我如何模仿新显示图层的行为,以便边框不会像从旋转后的旧位置。

我创建了这个示例项目 - 如果您愿意,可以剪切和粘贴。您只需要链接石英核心库。

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (nonatomic,strong) CALayer *layerThatKeepAnimating;
@end

@implementation ViewController

-(CALayer*) layerThatKeepAnimating
{
  if(!_layerThatKeepAnimating)
  {
    _layerThatKeepAnimating=[CALayer layer];
    _layerThatKeepAnimating.borderWidth=2;
  }
return _layerThatKeepAnimating;
}


-(void) viewDidAppear:(BOOL)animate
{    
self.layerThatKeepAnimating.frame=CGRectMake(self.view.bounds.size.width/2-50,self.view.bounds.size.height/2-50, 100, 100);
  [self.view.layer addSublayer:self.layerThatKeepAnimating];
}


-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  [self.layerThatKeepAnimating removeFromSuperlayer];
}


-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  self.layerThatKeepAnimating.frame=CGRectMake(self.view.bounds.size.width/2-50,self.view.bounds.size.height/2-50, 100, 100);
  [self.view.layer addSublayer:self.layerThatKeepAnimating];
}

@end
4

3 回答 3

0

听起来很奇怪,答案是将代码移入

willRotateToInterfaceOrientation 到视图WillLayoutSubviews

-(void) viewWillLayoutSubviews
{
    self.layerThatKeepAnimating.frame=CGRectMake(self.view.bounds.size.width/2-50,self.view.bounds.size.height/2-50, 100, 100);
    [self.view.layer addSublayer:self.layerThatKeepAnimating];
}

看起来这里的任何图层“重绘”都是在没有动画的情况下发生的,即使图层属性是可动画的。

于 2013-02-24T16:52:00.740 回答
0

问题不是你想的那样;当您从超级视图中删除该层时,它实际上并没有被取消,因为您保留了对它的强引用。您的代码不会在 getter 中输入 if 语句来创建新层,因为它在第一次之后永远不会为零:

if(!_layerThatKeepAnimating)
  {
    _layerThatKeepAnimating=[CALayer layer];
    _layerThatKeepAnimating.borderWidth=2;
  }

因此,要么将您对 vc 中层的引用更改为弱:

@property (nonatomic, weak) CALayer * layerThatKeepAnimating;

或通过以下方式明确删除它:

-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  [self.layerThatKeepAnimating removeFromSuperlayer];
  self.layerThatKeepAnimating = nil;
}

我建议您使用第一个选项,因为当您向视图添加图层(或子视图)时,您已经获得了一个强大的参考。这就是为什么总是建议这样做:

@property (weak, nonatomic) IBOutlet UIView *view;

但不是(强,非原子)。

于 2013-02-24T22:05:06.863 回答
0
[self.sublayerToRemove removeFromSuperlayer];
self.sublayerToRemove = nil;
于 2016-10-13T14:01:42.917 回答