On May 21, 2009, at 4:04 AM, Gwynne Raskind wrote:

I have a UIView that contains a number of CALayers. Nothing unusual here. The CALayers are subclassed to do their drawing, because that was easier than separating the delegate logic from my UIView subclass (since the view can't be the delegate of a sublayer - it causes an infinite recursion to do so, why isn't there a check for this somewhere in CA's or Cocoa Touch's code?).

Each time I call [anInstanceOfCALayer setNeedsDisplay], to update changes I've made to the layer's custom properties, Core Animation performs an implicit animation from the old cached data to the new draw state. For example, if I change a property so that my drawing code fills a path that was previously empty, the UI shows the filled space fading into existence.

I've figured out that I can explicitly disable this using the CATransaction calls wrapped around my call to -setNeedsDisplay. But I'd like to either:

1) animate the custom properties more directly with a CABasicAnimation. I tried this, but it did nothing at all.

2) get some control over the implicit animation CA is setting up for the contents transition. CATransaction only lets me set duration and the "is enabled" flag, whereas CAMediaTiming has a whole pile of useful parameters.

Any help would be appreciated.


Form your description, I can't see where the specific issue is. So I just post an example which will work (a modified working code, but changed for this example and not tested). Hope this helps:


I'm assuming you have a somewhat more complex layer hierarchy. Instead of subclassing a layer, I would define a "model" that has a visual representation in a UI. Say, this model is composed of a set of "shapes". But this design is up to you.

Instances of Shape are associated to a layer. It is assumed that a layer is only used by one shape. A Shape instance also has parameters which define a certain animation that will be triggered when a certain state change occurs on the instance:

Shape:
- (void) changeStateTo:(int)aState
{
    // Calculate the effect of a state change:
// In this example it is a rotation of the shape, which will be visualized by a single animation
    // that causes the layer to rotate:
    // (get the current rotation of this shape in radians)
    // (perform state change on the model)
    CGFloat fromRotation = self.currentRotation;
    [self private_changeStateTo:aState];
    CGFloat toRotation = self.currentRotation;

// Create a rotation animation around z axis by using animation parameters hold by the Shape instance:
    CABasicAnimation* animation = [CABasicAnimation animation];
    animation.keyPath = @"transform.rotation.z";
    animation.fromValue = [NSNumber numberWithFloat:fromRotation];
    animation.toValue = [NSNumber numberWithFloat:toRotation];
    animation.duration = (self.animationDuration);
    animation.repeatCount = 0;

// Leave the presentation layer in its final state (preventing snap-back to original state), // or in other words, match the state of the shape with its visual representation:
    // (note: there are alternatives to accomplish this)
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeBoth;

// Set a timing function (you may get required animation parameters from the Shape instance); animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

// The delegate may handle CAAnimation delegate methods. The shape instance itself would be a
    // good candidate to become the delegate:
    animation.delegate = self;

// Add the animation to the shapes's layer. Note that this immediately causes the animation to
    // start (asynchronously). setNeedsDisplay is not required!
// This will also stop a possibly running anmimation with the same key.
    [self.layer addAnimation:animation forKey:self.name];
}


Of course, you can setup any animation type, or an animation group.

The layer associated to a shape may be part of a layer hierarchy. Setting up the layer hierarchy that models the visual representation of your set of (possibly hierarchically layered) shapes is a different thing though, and not shown.

The delegate methods can be used to determine when the animation starts and when it has been finished, and whether it has been interrupted by another animation.

This method can be called from any thread.

This design moves completely the "how to animate a certain model state change" from the view controller to the many Shape classes that may exist in your application. So it can be easily extended by adding new sub classes of shape.


Regards
Andreas



-- Gwynne, Daughter of the Code
"This whole world is an asylum for the incurable."



_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/agrosam%40onlinehome.de

This email sent to agro...@onlinehome.de

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to