iOS-播放gif动画文件(OC方法)

iOS-.gif动画文件的播放

前言

播放gif动画的方法有多种:

  1. 将gif图片分解成多张图片使用UIImageView播放
  2. webView直接播放.gif文件
  3. 使用第三方播放

本文主要介绍的是这三种方法播放gif动画,并提供一个使用第三种方法制作的播放gif的loading实例。接下就步入正题吧(__)!


为了方便大家使用封装了一个可以在任意VIEW播放gif动画的工具类,欢迎使用!

VDGifPlayerTool.h

#import <Foundation/Foundation.h>

@interface VDGifPlayerTool : NSObject

- (void)addGifWithName:(NSString *)gifName toView:(UIView *)view;

@end

VDGifPlayerTool.m

#import "VDGifPlayerTool.h"
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

@interface VDGifPlayerTool()
@property (nonatomic, strong)UIView *gifContentView;

@property (nonatomic, assign)CGImageSourceRef gif;
@property (nonatomic, strong)NSDictionary *gifDic;
@property (nonatomic, assign)size_t index;
@property (nonatomic, assign)size_t count;
@property (nonatomic, strong)NSTimer *timer;

@end
@implementation VDGifPlayerTool

- (void)addGifWithName:(NSString *)gifName toView:(UIView *)view{
    self.gifContentView = view;
    [self createGif:gifName];
}

- (void)createGif:(NSString *)name{
    
    //    _gifContentView.layer.borderColor = UIColorFromRGB(No_Choose_Color).CGColor;
    //    _gifContentView.layer.borderWidth = 1.0;
    NSDictionary *gifLoopCount = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount];
    _gifDic = [NSDictionary dictionaryWithObject:gifLoopCount forKey:(NSString *)kCGImagePropertyGIFDictionary];
    
    NSData *gif = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]];
    _gif = CGImageSourceCreateWithData((CFDataRef)gif, (CFDictionaryRef)_gifDic);
    _count = CGImageSourceGetCount(_gif);
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(startLoading) userInfo:nil repeats:YES];
    [_timer fire];
}
-(void)startLoading
{
    _index ++;
    _index = _index%_count;
    CGImageRef ref = CGImageSourceCreateImageAtIndex(_gif, _index, (CFDictionaryRef)_gifDic);
    self.gifContentView.layer.contents = (__bridge id)ref;
    CFRelease(ref);
}
- (void)dealloc{
    if (_gif) {
        CFRelease(_gif);
    }
}
@end

一、UIImageView实现gif动画

用imageView制作gif动画最经典就是汤姆猫,感兴趣的可以百度或者谷歌一下“iOS汤姆猫源代码”。在这里只是简单的介绍imageview的gif动画实现,你也可以用计时器(NSTimer).在做这些之前必须要将gif分解成一张张PNG图片。

UIImageView *gifImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    gifImageView.center = self.view.center;
    [self.view addSubview:gifImageView];
    
    NSMutableArray *images = [NSMutableArray array];
    for (int i=0; i < 10; i++) {
        [images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"image%d",i]]];
    }
    gifImageView.animationImages = images;
    gifImageView.animationDuration = 5.0;
    gifImageView.animationRepeatCount = NSUIntegerMax;
    [gifImageView startAnimating];

二、UIWebView实现.gif动画文件的播放

webView可以加载很多文件是个很强大的控件,实现gif播放简单直接不过只能循环播放。

CGSize size = [UIImage imageNamed:@"name.gif"].size;
    UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, size.width, size.height)];
    webView.center = self.view.center;
    webView.userInteractionEnabled = NO;
    webView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:webView];
    NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"name" ofType:@"gif"]];
    [webView loadData:data MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];

三、第三方实现播放gif动画

首先需要导入两个库:ImageIO.frameworkMobileCoreServices.framework;具体实现是采用ImageIO库对.gif文件进行解析获取相关资源最后进行动画的播放,下面是自己写的播放gif动画的loading实例(比较简陋大家将就看看,知道怎么实现就行了_)。

GifLoadingView.h

#import <UIKit/UIKit.h>

@interface GifLoadingView : UIView
+(void)startLoading;
+(void)endLoading;
@end

GifLoadingView.m

#define  GIF_WIDTH 80*1.2
#import "GifLoadingView.h"
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
@interface GifLoadingView()
@property (nonatomic, strong)NSMutableArray<UIImage *> *images;
@property (nonatomic, strong)GifLoadingView *loading;
@property (nonatomic, strong)UIView *gifContentView;

@property (nonatomic, assign)CGImageSourceRef gif;
@property (nonatomic, strong)NSDictionary *gifDic;
@property (nonatomic, assign)size_t index;
@property (nonatomic, assign)size_t count;
@property (nonatomic, strong)NSTimer *timer;

@end
@implementation GifLoadingView
- (instancetype)init{
    self = [self initWithFrame:CGRectMake(0, 0, GIF_WIDTH, GIF_WIDTH)];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        self.layer.cornerRadius = GIF_WIDTH/2;
        self.layer.masksToBounds = YES;
        [self createGif];

    }
    return self;
}

- (void)createGif{
    
//    _gifContentView.layer.borderColor = UIColorFromRGB(No_Choose_Color).CGColor;
//    _gifContentView.layer.borderWidth = 1.0;
    NSDictionary *gifLoopCount = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount];
    _gifDic = [NSDictionary dictionaryWithObject:gifLoopCount forKey:(NSString *)kCGImagePropertyGIFDictionary];

    NSData *gif = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"loading" ofType:@"gif"]];
    _gif = CGImageSourceCreateWithData((CFDataRef)gif, (CFDictionaryRef)_gifDic);
    _count = CGImageSourceGetCount(_gif);
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(startLoading) userInfo:nil repeats:YES];
    [_timer fire];
}
-(void)startLoading
{
    _index ++;
    _index = _index%_count;
    CGImageRef ref = CGImageSourceCreateImageAtIndex(_gif, _index, (CFDictionaryRef)_gifDic);
    self.layer.contents = (__bridge id)ref;
    CFRelease(ref);
}
+ (void)startLoading{
    GifLoadingView *loading = [[GifLoadingView alloc]init];
    UIWindow *keyView = [UIApplication sharedApplication].keyWindow;
    loading.center = keyView.center;
    [keyView addSubview:loading];
    dispatch_main_after(5.0f, ^{
        [GifLoadingView endLoading];
    });
}
+ (void)endLoading{
    for (UIView *view in [UIApplication sharedApplication].keyWindow.subviews) {
        if ([view isKindOfClass:[GifLoadingView class]]) {
//            [UIView animateWithDuration:1.0 animations:^{
//                view.alpha = 0;
//            } completion:^(BOOL finished) {
               [((GifLoadingView *)view) stopGif];
               [view removeFromSuperview];
//            }];
        }
    }
    
}
- (void)stopGif
{
    [_timer invalidate];
    _timer = nil;
}
- (void)dealloc{
    CFRelease(_gif);
}

static void dispatch_main_after(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        block();
    });
}

总结

简要总结一些三个方法的利弊:

  1. UIImageView采用帧动画将图片一张张显示,这个方法可以调节播放次数和速度但图片过多过大内存会很有压力。另外在保证播放的动画清晰和时长的情况下.gif文件大小会远小于多张.png图片的大小。

  2. UIWebView实现播放gif特别简单直接,如果你只想单纯的播放一下建议使用此方法。弊端就是只能循环播放~~~(>_<)~~~,无法控制它的暂停和其他操作。

  3. 使用第三方播放gif动画集合了第一种方法好处你可以对动画进行一系列操作,在.gif文件比较大的情况下建议使用。(个人喜欢使用此方法)。


最后

我的第二次(写文章)就这么完了。以上很多观点为自己的个人看法不喜勿喷,当然喷了也没事。最后感谢那些能看完小爷这篇文章的小伙伴们,希望能够帮助到你们。( _ )/~~拜拜。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容