Search code examples
iosuiviewuiviewcontrollercalayerquartz-core

CALayer frame value causing animation even after removal from superlayer


Into the CALayer world:

I am creating a layer that needs to remain in middle of view regardless of device orientation. Can someone tell me why does my layer animates after rotation from the old position even though I removed it from superlayer? I understand that the frame and borderWidth properties are animatable but are they animatable even after removal from superLayer?

And if removal from superLayer does not reset the layer properties because the layer object has not been released (ok I can understand that), how do I mimic the behavior of a newly displayed layer so that the border does not shows like it is moving from an old position after rotation.

I created this sample project - cut and paste if you wish. You will just need to link the quartz core library.

#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

Solution

  • As odd as this sounds, the answer is to move code in

    willRotateToInterfaceOrientation to viewWillLayoutSubviews

    -(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];
    }
    

    It looks like any layer "redrawing" here happens without animation, even if layer properties are animatable.