views:

146

answers:

1

Hi,

I'm trying to define an abstract layer property, angle, based on the existing layer property position. Basically it describes the orientation of the layer from the center of a circle. I did like the following:

@interface MenuItemLayer : CALayer
  @property CGFloat angle;
@end

@implementation MenuItemLayer

+ (BOOL)needsDisplayForKey: (NSString*)key {
  if ([key isEqualToString: @"angle"]) return YES;
  return [super needsDisplayForKey: key];
}

- (void)drawInContext: (CGContextRef)context {
  [self renderInContext: context];
}

- (CGFloat)angle {
  CGPoint center = self.superlayer.center;
  CGPoint pos = self.position;
  return atan2f(pos.x - center.x, center.y - pos.y);
}

- (void)setAngle: (CGFloat)angle {
  CGPoint center = self.superlayer.center;
  CGFloat radius = 100;
  [CATransaction begin];
  [CATransaction setDisableActions: YES];
  self.position = CGPointMake(center.x + radius * sinf(angle),
                              center.y - radius * cosf(angle));
  [CATransaction commit];
}

@end


It works fine when I manually set the value with setAngle:, but the problem is that when I try to animate it with a CABasicAnimation, the view sustained by the MenuItemLayer doesn't move at all and stays at its original position, while I can see that setValue: and drawInContext: get called normally along with the progress of the animation and so the position property of the presentation layer get updated.

Anyone has some clues? Thanks!



----

Just noticed the following comment in the doc:

renderInContext:
This method renders directly from the layer tree, ignoring any animations added to the render tree. Renders in the coordinate space of the layer.


Does this mean that renderInContext: will always use model layer to render the image even in our case where the receiver of the drawInContext: method is a presentation layer? Could this be the cause of the problem? If so, should I always manually translate the layer to the right location represented by the presentation layer?

A: 

What do you intend this to do?

- (void)drawInContext: (CGContextRef)context {
  [self renderInContext: context];
}

What happens when you comment it out? I find that -renderInContext is most commonly used to render into a context for the sake of saving it as an image so this looks strange to me. A basic animation should be able to animate your property without a problem but overriding -drawInContext seems like it would only make sense if you're planning to do some custom drawing with CG.

Matt Long
Thanks for the answer. Nothing is drawn if I remove drawInContext:, which is natural because I'm using the needsDisplayForKey mechanism to notify the CA framework that my layer should be redrawn. What I intend with renderInContext is to just redraw the layer with the animated property value.
Kay
Can you update your answer and show me your CABasicAnimation code? Are you expecting your change to the angle custom property to also animate the position? There are two issues with that. One is that you've disabled the actions so the change to position won't animate. Second is I believe if you want to animate two properties (one custom, angle, and one position) you use two separate animations and an animation group. Except I think you're wanting your position to change and animate based on changes to angle, right?
Matt Long