美文网首页iOS开发学习iOS动画程序员
iOS-播放gif动画文件(OC方法)

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

作者: volientDuan | 来源:发表于2016-06-23 14:40 被阅读3461次

    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文件比较大的情况下建议使用。(个人喜欢使用此方法)。


    最后

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

    相关文章

      网友评论

      • ArrQing:这个 太好用了,谢谢楼主!
      • 雪山飞狐_91ae:楼主,第三种方法怎么控制播放速度啊
        volientDuan:@雪山飞狐_91ae 的确有限制 如果需要再快 可以选择丢帧的方式 -(void)startLoading方法中把index++改为index +=2 我没试 你可以试试:smile:
        雪山飞狐_91ae:@volientDuan 我使用的时候修改scheduledTimerWithTimeInterval发现确实可以改变速度,但是最快的速度好像有一个限制,再就不能再快了
        volientDuan:[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(startLoading) userInfo:nil repeats:YES],修改秒数可以调整速率; 建议你直接使用文章头部的工具类,亲测可用:blush:
      • cdfc7672b68f:当然帅气可行.
        volientDuan:感谢支持:blush:
      • 冰糖葫芦子:还可以用sd_web实现
        volientDuan:@冰糖葫芦子 嗯 谢谢分享 刚在文章头部更新了一个可以在任意view播放gif的工具类 有兴趣可以看看 嘻嘻
      • 了了此心:楼主好帅,写的漂亮
        volientDuan: @了了此心 谢谢支持Ծ ̮ Ծ,大家互相学习!┗(`ー´)┓
      • 91aec98191ee:就是楼主丑了点
        volientDuan:@91aec98191ee 晚上想不想睡床了 :smirk:

      本文标题:iOS-播放gif动画文件(OC方法)

      本文链接:https://www.haomeiwen.com/subject/iwandttx.html