Transaction Management Classes
Every modification to an animatable property of a layer must be part of a transaction. CATransaction
is the Core Animation class responsible for batching multiple animation operations into atomic updates to the display. Nested transactions are supported.
Core Animation supports two types of transactions: implicit transactions and explicit transactions. Implicit transactions are created automatically when an animatable property of a layer is modified by a thread without an active transaction and are committed automatically when the thread's run-loop next iterates. Explicit transactions occur when the application sends theCATransaction
class a begin message before modifying the layer, and a commit message afterwards.
Providing CALayer Content
You specify the content of a CALayer
instance in one of the following ways:
-
Explicitly set the
contents
property of a layer instance using aCGImageRef
that contains the content image. -
Specify a delegate that provides, or draws, the content.
-
Subclass
CALayer
and override one of the display methods.
Setting the Contents Property
A layer’s content image is specified by the contents
property to a CGImageRef
. This can be done from another object when the layer is created (as shown in Table 3) or at any other time.
Setting a layer’s contents property
CALayer *theLayer; |
|
// create the layer and set the bounds and position |
theLayer=[CALayer layer]; |
theLayer.position=CGPointMake(50.0f,50.0f); |
theLayer.bounds=CGRectMake(0.0f,0.0f,100.0f,100.0f); |
|
// set the contents property to a CGImageRef |
// specified by theImage (loaded elsewhere) |
theLayer.contents=theImage; |
Using a Delegate to Provide Content
You can draw content for your layer, or better encapsulate setting the layer’s content image by creating a delegate class that implements one of the following methods: displayLayer:
or drawLayer:inContext:
.
setNeedsDisplay
or
setNeedsDisplayInRect:
message, or by setting its
needsDisplayOnBoundsChange
property to
YES
.
Providing CALayer Content by Subclassing
CALayer
subclasses can draw the layer’s content into a graphics context by overriding drawInContext:
.
Subclassing CALayer
and implementing one of the drawing methods does not automatically cause drawing to occur. You must explicitly cause the instance to re-cache the content, either by sending it a setNeedsDisplay
orsetNeedsDisplayInRect:
message, or by setting its needsDisplayOnBoundsChange
property to YES
.
Position constant | Description |
---|---|
Positions the content image in the top left corner of the layer. | |
Positions the content image horizontally centered along the top edge of the layer. | |
Positions the content image in the top right corner of the layer. | |
Positions the content image vertically centered on the left edge of the layer. | |
Positions the content image at the center of the layer. | |
Positions the content image vertically centered on the right edge of the layer. | |
Positions the content image in the bottom left corner of the layer. | |
Positions the content image centered along the bottom edge of the layer. | |
Positions the content image in the top right corner of the layer. |
Scaling constant | Description |
---|---|
Resize the content image to completely fill the layer bounds, potentially ignoring the natural aspect of the content. This is the default. | |
Resize the content image to scale such that it is displayed as large as possible within the layer bounds, yet still retains its natural aspect. | |
Resize the content image to scale such that it is displayed filling the layer bounds, yet retaining its natural aspect. This may cause the content to extend outside the layer bounds. |
Core Animation provides an expressive set of animation classes you can use in your application:
-
CABasicAnimation
provides simple interpolation between values for a layer property. -
CAKeyframeAnimation
provides support for key frame animation. You specify the key path of the layer property to be animated, an array of values that represent the value at each stage of the animation, as well as arrays of key frame times and timing functions. As the animation runs, each value is set in turn using the specified interpolation. -
CATransition
provides a transition effect that affects the entire layer's content. It fades, pushes, or reveals layer content when animating. The stock transition effects can be extended by providing your own custom Core Image filters. -
CAAnimationGroup
allows an array of animation objects to be grouped together and run concurrently.
Implicit Animation
Core Animation’s implicit animation model assumes that all changes to animatable layer properties should be gradual and asynchronous. Dynamically animated scenes can be achieved without ever explicitly animating layers. Changing the value of an animatable layer property causes the layer to implicitly animate the change from the old value to the new value. While an animation is in-flight, setting a new target value causes the animation transition to the new target value from its current state.
Implicitly animating a layer’s position property
// assume that the layer is current positioned at (100.0,100.0) |
theLayer.position=CGPointMake(500.0,500.0); |
Explicit Animation
Core Animation also supports an explicit animation model. The explicit animation model requires that you create an animation object, and set start and end values. An explicit animation won’t start until you apply the animation to a layer.The animation doesn’t begin until it is added to the layer.
CABasicAnimation *theAnimation; |
|
theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"]; |
theAnimation.duration=3.0; |
theAnimation.repeatCount=2; |
theAnimation.autoreverses=YES; |
theAnimation.fromValue=[NSNumber numberWithFloat:1.0]; |
theAnimation.toValue=[NSNumber numberWithFloat:0.0]; |
[theLayer addAnimation:theAnimation forKey:@"animateOpacity"]; |
Starting and Stopping Explicit Animations
You start an explicit animation by sending a addAnimation:forKey:
message to the target layer, passing the animation and an identifier as parameters. Once added to the target layer the explicit animation will run until the animation completes, or it is removed from the layer. The identifier used to add an animation to a layer is also used to stop it by invokingremoveAnimationForKey:
. You can stop all animations for a layer by sending the layer a removeAllAnimations
message.
Layer Actions
Layer actions are triggered in response to: layers being inserted and removed from the layer-tree, the value of layer properties being modified, or explicit application requests. Typically, action triggers result in an animation being displayed.
There's no difference between an implicit animation and an explicit
animation. The only difference is that implicit animations are created
by the layer's -actionForKey: method in response to a property being
changed, while explicit animations are created by your code directly.
This is what happens when a layer property is modified:
1. Finds the "action" object associated with the property. If the
disableActions transaction property is true the action is nil,
otherwise, calls the -actionForKey: method, with the key being the key-
path of the property being changed. -actionForKey: does these things
to try to find a non-nil object: (the first that returns non-nil stops
the others from being tried)
1. calls the -actionForLayer:forKey: delegate method
2. looks in the layer's "actions" property (a dictionary)
3. walks up the "style" hierarchy looking in the "actions" property
of each style dictionary
4. calls the +defaultActionForKey: method.
5. if the key represents an animatable property, creates an animation
object to represent that animation.
any of these steps can return [NSNull null] to stop the search.
2. Calls the -willChangeValueForKey: method
3. Sets the property to its new value wherever that's stored
4. Calls the -didChangeValueForKey: method
5. If the action from step (1) is non-nil, invoke it's -
runActionForKey:object:arguments: method. In the case of CAAnimation,
this invokes the layer's -addAnimation:forKey: method to add the
animation to the layer (the key is the key-path of the changed
property.)
Hopefully that makes it clearer, the important thing is that an
implicit animation is just an explicit animation that was created
within a property setter via the -actionForKey: mechanism,
Defined Search Pattern for Action Keys
//- (id<CAAction>)actionForKey:(NSString *)event;
代理类:
-(id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
CVTransition *anim=nil;
if([event isEqualToString:@"contents"]){
anim=[CATransitionanimation];
anim.duration=2;
anim.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.type=@"cube";
anim.subtype=kCATransitionFromRight;
}
return anim;
//不执行任何动画
//return nil;
}
When the CALayer
implementation of actionForKey:
is invoked for an identifier the following search pattern is used:
-
If the layer has a delegate, and it implements the method
actionForLayer:forKey:
it is invoked, passing the layer, and the action identifier as parameters. The delegate’sactionForLayer:forKey:
implementation should respond as follows:-
Return an action object that corresponds to the action identifier.
-
Return
nil
if it doesn’t handle the action identifier. -
Return
NSNull
if it doesn’t handle the action identifier and the search should be terminated.
-
-
The layer’s
actions
dictionary is searched for an object that corresponds to the action identifier. -
The layer’s
style
property is searched for anactions
dictionary that contains the identifier. -
The layer’s class is sent a
defaultActionForKey:
message. It will return an action object corresponding to the identifier, ornil
if not found.
action 主要添加动画
- (void)runActionForKey:(NSString *)key |
object:(id)anObject |
arguments:(NSDictionary *)dict |
{ |
[(CALayer *)anObject addAnimation:self forKey:key]; |
} |
Overriding an Implied Animation
You can provide a different implied animation for an action identifier by inserting an instance of CAAnimation
into theactions
dictionary, into an actions dictionary in the style
dictionary, by implementing the delegate methodactionForLayer:forKey:
, or subclassing a layer class, overriding defaultActionForKey:
and returning the appropriate action object.
Transactions
the two types of transactions Core Animation supports: implicit transactions and explicit transactions.Implicit transactions are created automatically when the layer tree is modified by a thread without an active transaction, and are committed automatically when the thread's run-loop next iterates.
When modifying layer properties from threads that don’t have a runloop, you must use explicit transactions.
Explicit transactions are particularly useful when setting the properties of many layers at the same time (for example, while laying out multiple layers), temporarily disabling layer actions, or temporarily changing the duration of resulting implied animations.
[CATransaction begin]; |
[CATransaction setValue:(id)kCFBooleanTrue |
forKey:kCATransactionDisableActions]; |
[aLayer removeFromSuperlayer]; |
[CATransaction commit]; |
[CATransaction begin]; |
[CATransaction setValue:[NSNumber numberWithFloat:10.0f] |
forKey:kCATransactionAnimationDuration]; |
theLayer.zPosition=200.0; |
theLayer.opacity=0.0; |
[CATransaction commit]; |
[CATransaction begin]; // outer transaction |
|
// change the animation duration to 2 seconds |
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] |
forKey:kCATransactionAnimationDuration]; |
// move the layer to a new position |
theLayer.position = CGPointMake(0.0,0.0); |
|
[CATransaction begin]; // inner transaction |
// change the animation duration to 5 seconds |
[CATransaction setValue:[NSNumber numberWithFloat:5.0f] |
forKey:kCATransactionAnimationDuration]; |
|
// change the zPosition and opacity |
theLayer.zPosition=200.0; |
theLayer.opacity=0.0; |
|
[CATransaction commit]; // inner transaction |
|
[CATransaction commit]; // outer transaction |
Core Animation adds a new convention to key value coding that allows a class to provide a default value that is used when a class has no value set for that key. Both CALayer
or CAAnimation
support this convention using the class methoddefaultValueForKey:
.
To provide a default value for a key you create a subclass of the class and override defaultValueForKey:
. The subclass implementation examines the key parameter and then returns the appropriate default value. Listing 1 shows an example implementation of defaultValueForKey:
that provides a new default value for the layer property masksToBounds
.
Example implementation of defaultValueForKey:
|
+ (id)defaultValueForKey:(NSString *)key |
{ |
if ([key isEqualToString:@"masksToBounds"]) |
return [NSNumber numberWithBool:YES]; |
|
return [super defaultValueForKey:key]; |
} |
The repeatCount
specifies the number of times the animation should repeat and can be a fractional number. Setting the repeatCount
to a value of 2.5 for a 10 second animation would cause the animation to run for a total of 25 seconds, ending half way through its third iteration. Setting the repeatCount to 1e100f
will cause the animation to repeat until it is removed from the layer.
The fillMode
property of the timing protocol defines how an animation will be displayed outside of its active duration. The animation can be frozen at its starting position, at its ending position, both, or removed entirely from display. The default behavior is to remove the animation from display when it has completed.