由于我们的项目需要,我正在写一个播放序列帧的程序,第一时间想起来的就是apple中UIImageView的属性animationImages,将一系列帧添加到一个数组里面,然后设置animation一系列属性,如动画时间,动画重复次数,还是看代码吧,直观
- myImages = [NSArray arrayWithObjects:
- [UIImage imageNamed:@"mario_1.png"],
- [UIImage imageNamed:@"mario_2.png"],
- [UIImage imageNamed:@"mario_3.png"],
- [UIImage imageNamed:@"mario_4.png"],
- [UIImage imageNamed:@"mario_5.png"],nil];
- myAnimatedView = [UIImageView alloc];
- [myAnimatedView initWithFrame:CGRectMake(0, 0, 131, 125)];
- myAnimatedView.animationImages = myImages;//将序列帧数组赋给UIImageView的animationImages属性
- myAnimatedView.animationDuration = 0.25;//设置动画时间
- myAnimatedView.animationRepeatCount = 0;//设置动画次数 0 表示无限
- [myAnimatedView startAnimating];//开始播放动画
- [self addSubview:myAnimatedView];
之后我们考虑了自己去实现UIImageView的animation效果,题目之所以说他不给力,因为UIImageView的animation不会边用边释放(当然这点仅是我自己的拙见),那就导致了如果图片很多,animation直接崩掉根本用不了,我们实现的原理就是用NSTimer去实现apple的UIImageView animation的效果,其实apple应该也是用NSTimer去实现吧(猜的),用NSTimer每隔一个时间戳去设置一次image,代码如下
- NSTimer *myAnimatedTimer = [NSTimer scheduledTimerWithTimeInterval:0.04 target:self selector:@selector(setNextImage) userInfo:nil repeats:YES];
- void setNextImage
- {
- myAnimatedView.image = [UIImage imageNamed:[NSString stringWithFormat:@"image%i.png",nextImage]];
- }
这样,如果图片很多的话,我们可以先加载一部分序列帧,当这一部分序列帧播放完成后,将之前播放过的序列帧(会一直在内存停留)释放掉,然后加载下一部分即将播放的序列帧,这样程序不至于崩掉,而且我们自己用timer去实现ImageView animation之后还可以暂停到指定的帧,然后恢复继续从暂停前的状态播放,任意帧到任意帧的跳转,横扫(swipe)加速,加速后会慢慢减速到停止或者到匀速,这一切的控制都变的很自由了。
下面是部分代码结构
- //
- // SXAnimationImageView.h
- //
- // Created by ShinSuo on 12-2-12.
- // Copyright (c) 2012年 CocoaChina. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- #define LEFT -1
- #define RIGHT 1
- typedef enum {
- SXAnimationImageViewStatePlaying,
- SXAnimationImageViewStateStop,
- SXAnimationImageViewStateStoped,
- // add State
- }SXAnimationImageViewState;
- typedef enum {
- SXAnimationImageViewPre,
- SXAnimationImageViewNext,
- }SXAnimationImageViewPreOrNext;
- @interface SXAnimationImageView : UIView
- {
- UIImageView * _imageView;
- NSTimer * _timer;
- NSUInteger _currentIndex;
- NSUInteger _jump;
- SXAnimationImageViewPreOrNext _preOrNext;
- UIPanGestureRecognizer * _panGesture;
- // add Gesture
- }
- @property NSTimeInterval animationDuration;
- @property NSUInteger animationRepeatCount;
- @property NSUInteger toIndex;
- @property (strong,nonatomic) NSMutableArray * animationImages;
- - (void)animationTo:(NSUInteger)index_;
- - (void)setCurrentImage;
- - (void)startAnimating;
- - (void)stopAnimating;
- - (BOOL)isAnimating;
- @end
部分实现文件代码
- //
- // SXAnimationImageView.m
- //
- // Created by ShinSuo on 12-2-12.
- // Copyright (c) 2012年 CocoaChina. All rights reserved.
- //
- #import "SXAnimationImageView.h"
- @interface SXAnimationImageView ()
- - (void)preCache;// prepare read image
- - (void)animationFrom:(NSUInteger)fromIndex_ To:(NSUInteger)toIndex_;
- - (void)waitForStop:(NSNotification *)notification;
- - (void)stateChanged:(NSNotification *)notification;
- @end
- @implementation SXAnimationImageView
- @synthesize animationDuration = _animationDuration;
- @synthesize animationRepeatCount = _animationRepeatCount;
- @synthesize toIndex = _toIndex;
- @synthesize animationImages = _animationImages;
- - (void)setAnimationImages:(NSMutableArray *)animationImages_
- {
- if (_animationImages == nil) {
- _animationImages = [[NSMutableArray alloc] init];
- }
- _animationImages = animationImages_;
- [self preCache];
- }
- - (void)preCache
- {
- _imageView.animationImages = _animationImages;
- _imageView.animationDuration = 0.4;
- _imageView.animationRepeatCount = 1;
- [_imageView startAnimating];
- [_imageView performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.41];
- }
- @end
这个实现文件中有一个投机取巧的地方,有些同学应该注意到了,就是 preCache,这里这种方法也仅限于图片比较少的时候,如果图片很多的话是不可取的照样会崩的,用过UIImageView animationImages属性的应该知道,第一次加载的时候会很慢,animation完成一次周期之后就很流畅了,那么我们这里,在程序启动的时候可以先将对
SXAnimationImageView的animationImages赋值(会调用 preCache),这样当视图没有加载的时候其实已经完成一次动画了,只是你没有看到,等程序启动起来后视图显示在你眼前的时候动画已经很流畅了。
由于代码现在主要是为我们这个项目写的,所以不够通用,等我们这个项目over后我会将自己实现的这个ImageView动画修改下,上传到git供大家使用