涉及动画的一些代码
时间: 2010-02-03 11:03 点击: 次
当你做一个软件的动画时,你会花费大量时间在控制动画的代码上。通常,视图控制器的代码会花费大量时间在检测动画各图层的完成情况上。动画多了以后,用这种方法就非常麻烦。
英文原文 http://weblog.bignerdranch.com/?p=215
当你做一个软件的动画时,你会花费大量时间在控制动画的代码上。通常,视图控制器的代码会花费大量时间在检测动画各图层的完成情况上。动画多了以后,用这种方法就非常麻烦。你必须为每个动画里的元素设置代号,并防止他们播放完了就消失。为此你不得不写一大堆重复的代码。
要是像控制UI那样控制动画该多简单,每个图层的动画完成时,都会触发此前预设的行为。这样,你就控制一段动画完成以后继续播放动画或执行代码。
怎么实现呢?看看“CALayer”子类,图层和动画间有很好的对应关系。下面是这个子类的代码:
当你做一个软件的动画时,你会花费大量时间在控制动画的代码上。通常,视图控制器的代码会花费大量时间在检测动画各图层的完成情况上。动画多了以后,用这种方法就非常麻烦。你必须为每个动画里的元素设置代号,并防止他们播放完了就消失。为此你不得不写一大堆重复的代码。
要是像控制UI那样控制动画该多简单,每个图层的动画完成时,都会触发此前预设的行为。这样,你就控制一段动画完成以后继续播放动画或执行代码。
怎么实现呢?看看“CALayer”子类,图层和动画间有很好的对应关系。下面是这个子类的代码:
BNRActionLayer.h:
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
@interface BNRActionLayer : CALayer {
NSMutableDictionary *targetActionPairs;
}
- (void)addTarget:(id)t action:(SEL)a forKey:(NSString *)k;
- (void)removeTarget:(id)t action:(SEL)a forKey:(NSString *)k;
- (NSArray *)actionsForTarget:(id)t forKey:(NSString *)k;
@end
BNRActionLayer.m:
#import "BNRActionLayer.h"怎么使用呢?确保图层使用的类型为BNRActionLayer
// Declare a private class to keep track of target-action pairs
@interface BNRActionLayerTargetActionPair : NSObject
{
id target;
SEL action;
}
@property (nonatomic, assign) id target;
@property (nonatomic, assign) SEL action;
@end
@implementation BNRActionLayerTargetActionPair
@synthesize target, action;
@end
@interface BNRActionLayer (Private)
- (NSMutableArray *)pairsForKey:(NSString *)k;
@end
@implementation BNRActionLayer
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
for(NSString *observedKey in targetActionPairs) {
if([self animationForKey:observedKey] == theAnimation) {
NSArray *pairs = [self pairsForKey:observedKey];
[self removeAnimationForKey:observedKey];
for(BNRActionLayerTargetActionPair *pair in pairs) {
if(flag)
[[pair target] performSelector:[pair action]
withObject:self];
}
}
}
}
- (void)addAnimation:(CAAnimation *)theAnimation forKey:(NSString *)key
{
NSArray *targetActionsForThisKey = [targetActionPairs objectForKey:key];
if([targetActionsForThisKey count] > 0) {
[theAnimation setRemovedOnCompletion:NO];
[theAnimation setDelegate:self];
}
[super addAnimation:theAnimation forKey:key];
}
- (void)addTarget:(id)t action:(SEL)a forKey:(NSString *)k
{
if(!targetActionPairs)
targetActionPairs = [[NSMutableDictionary alloc] init];
NSMutableArray *pairsForKey = [self pairsForKey:k];
if(!pairsForKey) {
pairsForKey = [NSMutableArray array];
[targetActionPairs setObject:pairsForKey forKey:k];
}
for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
if([pair target] == t && [pair action] == a)
return;
}
BNRActionLayerTargetActionPair *newPair =
[[BNRActionLayerTargetActionPair alloc] init];
[newPair setTarget:t];
[newPair setAction:a];
[pairsForKey addObject:newPair];
[newPair release];
}
- (void)removeTarget:(id)t action:(SEL)a forKey:(NSString *)k
{
NSMutableArray *pairsForKey = [self pairsForKey:k];
if(!pairsForKey)
return;
BNRActionLayerTargetActionPair *removablePair = nil;
for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
if([pair target] == t && [pair action] == a) {
removablePair = pair;
break;
}
}
[pairsForKey removeObject:removablePair];
}
- (NSMutableArray *)pairsForKey:(NSString *)k
{
return [targetActionPairs objectForKey:k];
}
- (NSArray *)actionsForTarget:(id)t forKey:(NSString *)k
{
NSMutableArray *list = [NSMutableArray array];
NSMutableArray *pairsForKey = [self pairsForKey:k];
for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
if([pair target] == t)
[list addObject:NSStringFromSelector([pair action])];
}
return [NSArray arrayWithArray:list];
}
- (void)dealloc
{
[targetActionPairs release];
[super dealloc];
}
@end
@implementation MyView
+ (Class)layerClass
{
return [BNRActionLayer class];
}
@end
当你创建 MyView 实例时, 可以为他添加目标行为.
- (void)applicationDidFinishLaunching:(UIApplication *)app然后需要实现viewDidFadeIn,假设一种视角,使得这一切是可触的
{
MyView *v = [[[MyView alloc] initWithFrame:someRect] autorelease];
[window addSubview:v];
[(BNRActionLayer *)[v layer] addTarget:self
action:@selector(viewDidFadeIn:)
forKey:@"Fade In"];
[window makeKeyAndVisible];
}
- (void)viewDidFadeIn:(BNRActionLayer *)layer
{
// We can operate on the layer here, do some controllery stuff, and we
// can also get the this layers owning view. An implicit layer's delegate
// is always its view (on the iPhone).
MyView *v = [layer delegate];
[v setUserInteractionEnabled:YES];
}
那如何创建一个播放完成后能发送信息的动画呢?用同样的方法创建一个动画
- (void)activateView:(MyView *)v
{
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
[a setToValue:[NSNumber numberWithFloat:1]];
[a setDuration:1];
// The key here matches the key the target-action pair was added for
[[v layer] addAnimation:a forKey:@"Fade In"];
}
很酷吧,声明:我用了几天没发现问题。当然,这并不意味着代码是完美的,只是给您提个醒。
顶一下(3)
100%
踩一下(0)
0%
打印 上一篇:查看程序运行时间的代码
下一篇:XCode模板
发表评论
本类文章点击排行榜
- [06-18] Cocoa夜未央第一期 Cocoa的基本
- [06-18] UITableView实例教程:创建Tabl
- [06-18] Cocoa夜未央第三期 MVC,界面编
- [06-18] Cocoa夜未央第二期 xcode及基本
- [06-11] Google的开源苹果软件更新框架
- [06-02] XCode自带Source Control Manager(SC
- [06-11] Leopard轻松编程:帮你节省代码
- [06-11] WebKit的基本用法
- [06-18] NSLog 输出格式
推荐内容
最近更新
- [07-09] NSSlider控件出现残像的解决方法
- [07-07] 调用系统现成importer来获取文件metadata的方法
- [06-30] 实现鼠标拖拽删除对象时烟雾缭绕效果的代码
- [06-28] QuickLook 调用示例代码
- [06-22] Cocoa里的字符串,NSString介绍
- [06-22] Cocoa里参数传递引用的方法
- [06-21] 在 xcode中进行条件编译的方法
- [06-18] 将iPhone的png图片转换为可读png图片的Python源码
- [06-18] 在苹果应用程序里打开PDF文档的方法
相关文章
- [06-28] QuickLook 调用示例代码
- [03-26] NIB 和 XIB 的区别
- [02-03] 在Cocoa里使用UUID
- [02-02] 查看程序运行时间的代码
- [06-18] UITableView实例教程:创建Table View的detail view
- [06-11] 小技巧:使NSPanel窗口正确响应托管事件
- [06-11] 允许/禁用应用程序中的菜单项
- [06-11] Leopard轻松编程:帮你节省代码

XCode自带Source Control Manager(SCM)以及SnapShots用法
XCode、Cocoa开发中使用第三方dylib的方法
[系统控件重绘教程(二)]重绘NSButton
创建Xcode自定义模板的图文教程
在Cocoa中使用TagLib获取歌曲ID3信息
iLife 08风格的Source List代码