UIImageView动画在startAnimating发出几秒后启动

时间:2010-08-17 11:59:39

标签: iphone animation uiimageview

好的,我有以下非常简单的动画,由PNG格式的25帧组成。每帧为320×360,大小约为170Kb。这是我使用的代码

·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];

在模拟器上,所有东西都会在发出startAnimating的同时启动良好的视觉动画。

但是在运行iOS 4.0.2的iPhone 3G上,视觉动画在startAnimating发布后的2到3秒内启动。

我已经尝试过在博客或论坛中找到的每种技术都应该解决这个问题无济于事。

任何提示都会受到赞赏,即使它是基于PNG的动画的完全不同的方式。

感谢。

3 个答案:

答案 0 :(得分:5)

这是一个很好的问题,我将在这里提出一些想法。

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

.h 文件的 @interface 块中,您可能需要声明两个属性,例如:

IBOutlet UIImageView *animationViewNormal;
NSMutableArray *animationViewNormalImages;

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

@interface .m 文件中,创建以下方法:

- (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];
  ...
}

Last(应该是我们添加 .m 文件的第二件事)我们在 dealloc()中的可变数组中进行清理:

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

这就是我们处理它并为我们工作的方式,但是我们通常不会将4MB图像加载到内存中来制作动画。

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

为了表现,您可能需要考虑以下因素:

  • 将不透明视图标记为: 合成内容为的视图 不透明需要的努力要少得多 合成一个部分 透明。要使视图不透明, 视图的内容一定不能 包含任何透明度和 视图的不透明属性必须为
    设为是。
  • 从不透明PNG中删除Alpha通道 files:如果是PNG图像的每个像素 是不透明的,删除alpha 通道避免了混合的需要 包含该图像的图层。这个 简化了图像的合成 大大改善了绘图 性能

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

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

我希望这会有所帮助,如果确实如此,请将其投票。

最佳, 凯文 Able Pear Software

答案 1 :(得分:2)

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

您可以尝试的一件事是将其切换为imageNamed:,即

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

imageNamed:通常要快得多,但往往会无限期地缓存图像。

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

答案 2 :(得分:0)

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