2010-08-17 102 views
1

好吧,我有以下非常简单的动画,由25帧PNG格式组成。每个帧都是320×360,大小约为170Kb。这里是我的代码使用启动动画发出后几秒钟UIImageView动画开始

.H:

IBOutlet UIImageView *Animation_Normal_View; 

在Interface Builder中我有一个参考的出口指向这一个UIImageView。我的所有图像都命名normal_000_crop.png,normal_001_crop.png,normal_002_crop.png,...

.M:

Animation_Normal = [[NSMutableArray alloc] initWithCapacity:25]; 
for (int i = 0; i < 25; i++) 
{ 
    [Animation_Normal addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"normal_%03d_crop.png", i] ofType:nil]]]; 
} 

Animation_Normal_View.animationImages = Animation_Normal; 
Animation_Normal_View.animationDuration = 1; // seconds 
Animation_Normal_View.animationRepeatCount = 0; // 0 = loops forever 
[Animation_Normal release]; 


[self.view addSubview:Animation_Normal_View]; 
[Animation_Normal_View startAnimating]; 

在模拟器上的一切loogs良好的视觉动画开始为SOOS作为startAnimating发出。

但是在运行iOS 4.0.2的iPhone 3G上,可视动画在startAnimating发布后的2到3秒内开始良好。

我已经尝试过关于我可以在博客或论坛中找到的应该解决这个问题的所有技巧。

即使它是完全不同于基于PNG的动画完全不同的方式,也可以使用任何提示。

谢谢。

回答

2

imageWithContentsOfFile:往往需要很长时间来处理,特别是如果有很多文件(25是很多的)和/或他们很大。

有一两件事你可以尝试是将其切换出去imageNamed:,即

[UIImage imageNamed:[NSString stringWithFormat:@"normal_%03d_crop.png", i]] 

imageNamed:一般是要快得多,但往往或多或少无限期缓存图像。

如果将图像加载到内存中并在整个应用程序中保留它们是不可接受的,那么您可能需要做一些微调的事情来在适当的时间加载它们并在它们被使用后卸载它们。这些东西总是很棘手,并且需要多线程才能在加载时阻止主UI。但可行。有一些例子。

5

这是一个很好的问题,我会在这里解决它的一些想法。

首先,您正在加载一系列总大小为4MB左右的图形。这可能需要一些时间,特别是在较慢(较旧)的设备上。

在你.H文件的@interface块可能要声明两个属性,如:

IBOutlet UIImageView *animationViewNormal; 
NSMutableArray *animationViewNormalImages; 

第一个是你已经有UIImageView的(刚刚更名的最佳实践),第二个是可变数组,用于保存图像视图的图像堆栈。让我说,如果“正常”意味着状态。为了澄清,你是否正在为不同的状态加载额外的图像集?

在你的。米文件中的@interface创建以下方法:

- (void)loadAnimationImages; 

这将提供功能给图像堆栈导致在头中定义的可变数组。

@implementation相同.M文件,你会希望以下内容:

- (void)loadAnimationImages { 
    for (NSUInteger i = 0; i < 23; i++) { 
    NSString *imageName = [NSString stringWithFormat:@"normalCrop%03u", i]; 
    UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:@"png"]]; 
    if (image) { 
     [animationViewNormalImages addObject:image]; 
    } 
    } 
} 

正如你可以看到我改名为PNG文件从normal_%03u_crop至normalCrop%03U为最好的做法是将索引标签放在文件名的末尾(也是大多数应用程序会以这种方式输出内容)。循环加载图像,检查它是否为图像,然后将图像添加到可变数组中的“图像堆栈”。

的init()你需要以下条件:

- (id)init { 
    ... 
    animationViewNormalImages = [[NSMutableArray alloc] init]; 
    ... 
} 

此分配(animationViewNormalImages)可变数组来保存你的图像栈的图像视图。

我们现在转移到了代号为viewDidLoad中()

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    ... 
    [self loadAnimationImages]; 
    [animationViewNormal setAnimationImages:animationViewNormalImages]; 
    [animationViewNormal setAnimationDuration:1.1f]; 
    [animationViewNormal setAnimationRepeatCount:0]; // 0=infinite loop 
    ... 
} 

我们图像堆栈装入可变数组然后设置我们的ImageView的性能与图像栈,持续时间和重复次数。

接下来在viewDidAppear()我们启动图像视图动画:

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    ... 
    [animationViewNormal startAnimating]; 
    ... 
} 

一旦ImageView的是动画作为一个无限循环,我们需要留在viewWillDisappear视图(当处理)

- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    ... 
    [animationViewNormal stopAnimating]; 
    ... 
} 

末(这应该是我们添加.M文件中的第二件事情),我们清理的可变ARRA在的dealloc(Y)

- (void)dealloc { 
    ... 
    [animationViewNormalImages release]; 
    [super dealloc]; 
} 

这是我们如何处理它,并为我们工作,但话又说回来,我们通常不加载图像的4MB到内存中的动画。

.PNG文件在构建应用程序时被压缩,我不确定它们是否在加载资源包的图像时被动态地解压缩。这是一个布尔值,用于构建属性构建设置(COMPRESS_PNG_FILES)。

出于性能方面,你可能要考虑以下几点:

  • 马克不透明的意见,例如: 其复化内容 不透明需要比 合成一个是部分 透明的精力要少得多的视图。要使视图不透明,视图的内容不得包含任何透明度,并且 视图的不透明属性必须为
    设置为YES。从不透明PNG文件
  • 删除alpha通道:如果一个PNG图像 的每个像素是不透明的,在去除阿尔法 信道避免了需要混合含有该图像的 层。这 大大简化了图像 的合成,并提高了绘制 的性能。

此外,您可能会发现使用全部24帧(由各个帧的宽度偏移)制作一个大图像并将其加载一次会更好。然后使用Core Graphics与CGContextClipToRect然后只是偏移图像上下文。这意味着更多的代码,但可能比使用标准堆栈方法更快。

最后,您可能要考虑将.PNG文件转换为.PVR(PVRTC)文件。更多信息可以在这里找到:Apple Tech QA,Apple DocsSample Code

我希望这会有所帮助,如果是的话请投票。

最佳, 凯文 能够梨软件

+0

哇凯文!感谢您花时间写下所有这些内容。我还没有完全消化它,但会仔细阅读。 再次感谢你。这就是软件开发人员社区的全部内容! – user422808 2010-08-19 00:37:30

0

负载使用启动动画方法之前,这些图像。我建议一个更简单的方法“在applicationDidEnterForeground中调用start动画方法,当调用这个时不要忘记你的UIImageView的alpha属性,如果你设置uiimageiew.alpha = 0.01,像这样,你的开始动画方法将被调用,用户看不到这个动画“,所以不会有任何滞后。