iOS 4种方法显示GIF
【摘要】
GIF作为一种淘汰的图像类型文件,和flash一样,直至现在依然存在于我们生活中的每一个角落。
有时候在iOS中使用GIF会比使用帧动画来的更加方便。
iOS中加载GIF的方法大致分为以下几类:
(1)使用UIWebView播放GIF数据流。弊端是GIF图片只能播放一次(网上的很多博客都说可以播放,不知道是不是iOS版本的问题,还...
GIF作为一种淘汰的图像类型文件,和flash一样,直至现在依然存在于我们生活中的每一个角落。
有时候在iOS中使用GIF会比使用帧动画来的更加方便。
iOS中加载GIF的方法大致分为以下几类:
(1)使用UIWebView播放GIF数据流。弊端是GIF图片只能播放一次(网上的很多博客都说可以播放,不知道是不是iOS版本的问题,还是这可以播放指的就是1次)
(2)将GIF制作成一个本地网页,用UIVebView显示这个网页。弊端是GIF同样只能播放一次。
(2)预先将GIF中的图片提取出来,然后UIImageView每隔一定间隔显示一张图片。
(3)在运行时,通过代码提取GIF中的每一帧和间隔时间,通过帧动画CAKeyframeAnimation来播放。(该方法有点问题,每一帧的信息都能获取的到,但是动画无法播放,因此我还在调试,敬请期待)。
下面是实现以上技术的关键代码:
1、ViewController.m
//
// ViewController.m
// GifDemo
//
// Created by 555chy on 6/17/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import "ViewController.h"
//#import <MobileCoreServices/MobileCoreServices.h>
#import "GifView.h"
#define IMAGE_NAME @"resource/20140830549"
#define IMAGE_TYPE @"gif"
@interface ViewController () {
CGRect contentRect;
}
@end
@implementation ViewController
CGRect screenRect;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = @"chy龙神";
[self getContentRect];
/*
extern const CFStringRef kUTTypeJPEG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeJPEG2000 __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeTIFF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypePICT __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeGIF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypePNG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeQuickTimeImage __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeAppleICNS __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeBMP __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeICO __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
extern const CFStringRef kUTTypeRawImage __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
extern const CFStringRef kUTTypeScalableVectorGraphics __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
extern const CFStringRef kUTTypeLivePhoto __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_9_1);
*/
[self loadGifInWebView1];
[self loadGifInWebView2];
[self loadGifInImageView];
[self loadGifInGifView];
}
-(void)getContentRect {
screenRect = [UIScreen mainScreen].bounds;
contentRect = self.navigationController.navigationBar.frame;
NSLog(@"navigationRect = (%f,%f) %f*%f", contentRect.origin.x, contentRect.origin.y, contentRect.size.width, contentRect.size.height);
contentRect.origin.y = contentRect.size.height;
contentRect.size.height = screenRect.size.height - contentRect.size.height;
}
//使用webview加载gif只能不放一轮,不能循环播放
-(void)loadGifInWebView1 {
NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
NSData *gifData = [NSData dataWithContentsOfFile:path];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
//禁止回弹
webView.scrollView.bounces = NO;
webView.scrollView.scrollEnabled = NO;
webView.scalesPageToFit = YES;
//设置透明背景(webview的默认背景上灰色的)
webView.backgroundColor = [UIColor clearColor];
webView.opaque = 0;
//禁止交互
webView.userInteractionEnabled = NO;
[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:@"UTF-8" baseURL:[NSURL fileURLWithPath:@""]];
[self.view addSubview:webView];
}
-(void)loadGifInWebView2 {
NSURL *resourceUrl = [NSBundle mainBundle].resourceURL;
NSString *html = [NSString stringWithFormat:@"<html><body><img src=\"%@.%@\"></body></html>", IMAGE_NAME, IMAGE_TYPE];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x+contentRect.size.width/2, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
[webView loadHTMLString:html baseURL:resourceUrl];
[self.view addSubview:webView];
}
//普通的UIImage只能显示gif图片的第一帧
-(void)loadGifInImageView {
NSArray *gifImageNameArray = [[NSArray alloc] initWithObjects:@"1",@"5",@"10",@"16", nil];
NSMutableArray *gifImageArray = [NSMutableArray array];
for(int i=0; i<gifImageNameArray.count; i++) {
NSString *name = [NSString stringWithFormat:@"resource/gif/%@", [gifImageNameArray objectAtIndex:i]];
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:path];
[gifImageArray addObject:image];
}
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(contentRect.origin.x, contentRect.origin.y+contentRect.size.height/2, contentRect.size.width/2, contentRect.size.height/2)]; [self.view addSubview:imageView];
imageView.animationImages = gifImageArray;
//动画执行的总时长
imageView.animationDuration = 4*0.15;
//动画重复次数(0为重复播放)
imageView.animationRepeatCount = 0;
[imageView startAnimating];
/*
typedef NS_ENUM(NSInteger, UIViewContentMode) {
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent
UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.
UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter, // contents remain same size. positioned adjusted.
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
};
*/
imageView.contentMode = UIViewContentModeScaleToFill;
//imageView.contentMode = UIViewContentModeScaleAspectFit;
//imageView.contentMode = UIViewContentModeScaleAspectFill;
//imageView.contentScaleFactor = [UIScreen mainScreen].scale;
//imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
imageView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:imageView];
}
-(void)loadGifInGifView {
NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
GifView *gifView = [[GifView alloc] initWithFrame:CGRectMake(contentRect.origin.x+contentRect.size.width/2, contentRect.origin.y+contentRect.size.height/2, contentRect.size.width/2, contentRect.size.height/2) gifFileURL:[NSURL fileURLWithPath:path]];
//[gifView startGif];
[self.view addSubview:gifView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
2、GifView.h
//
// GifView.h
// GifDemo
//
// Created by 555chy on 6/18/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <ImageIO/ImageIO.h>
#import <QuartzCore/QuartzCore.h>
@interface GifView : UIImageView
-(id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL;
-(BOOL) startGif;
-(void) stopGif;
@end
3、GifView.m
//
// GifView.m
// GifDemo
//
// Created by 555chy on 6/18/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import "GifView.h"
void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime, CGFloat *gifWidth, CGFloat *gifHeight) {
CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);
size_t frameCount = CGImageSourceGetCount(gifSource);
NSLog(@"gif frame count = %ld", frameCount);
for(size_t i=0; i<frameCount; i++) {
//get each frame
CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
//[frames addObject:(id)frame];
//Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
[frames addObject:(id)CFBridgingRelease(frame)];
//这边不需要手动释放了,因为CFBridgingRelease已经把管理权交给ARC了
//CGImageRelease(frame);
//get gif info with each frame
//Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
//NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);
NSDictionary *dict = (NSDictionary*)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL));
NSLog(@"kCGImagePropertyGIFDictionary %@", [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary]);
//get gif size
if(gifWidth != NULL && gifHeight != NULL) {
*gifWidth = [[dict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];
*gifHeight = [[dict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];
NSLog(@"%ld. gif width*height = %f*%f", i, *gifWidth, *gifHeight);
}
//get gif property
NSDictionary *gifPropertyDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
//kCGImagePropertyGifDictionary中kCGImagePropertyGIFDelayTime, kCGImagePropertyGIFUnclampedDelayTime的值是一样的
id delayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime];
NSLog(@"delayTimeObject = %@", delayTimeObj);
[delayTimes addObject:delayTimeObj];
id unclampedDelayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFUnclampedDelayTime];
NSLog(@"unclampedDelayTimeObj = %@", unclampedDelayTimeObj);
//[delayTimes addObject:unclampedDelayTimeObj];
if(totalTime) {
*totalTime = *totalTime + [delayTimeObj floatValue];
}
}
NSLog(@"totalTime = %f", *totalTime);
CFRelease(gifSource);
}
@interface GifView() {
NSMutableArray *_gifFrames;
NSMutableArray * _gifFrameDelayTimes;
CGFloat _gifTotalTime;
CGFloat _gifWidth;
CGFloat _gifHeight;
}
@end
@implementation GifView
- (id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL {
self = [super initWithFrame:frame];
if(self) {
_gifFrames = [[NSMutableArray alloc] init];
_gifFrameDelayTimes = [[NSMutableArray alloc] init];
_gifWidth = 0;
_gifHeight = 0;
if(fileURL) {
getFrameInfo((__bridge CFURLRef) fileURL, _gifFrames, _gifFrameDelayTimes, &_gifTotalTime, &_gifWidth, &_gifHeight);
}
}
return self;
}
- (BOOL) startGif
{
CGFloat currentTime = 0;
unsigned int count = (unsigned int)_gifFrameDelayTimes.count;
NSLog(@"gif frame count = %u", count);
if(count <= 0 || _gifTotalTime <= 0) {
return NO;
}
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
NSMutableArray *times = [NSMutableArray arrayWithCapacity:count];
for(unsigned int i=0; i<count; i++) {
[times addObject:[NSNumber numberWithFloat:(currentTime/_gifTotalTime)]];
currentTime += [[_gifFrameDelayTimes objectAtIndex:i] floatValue];
}
[animation setKeyTimes:times];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:count];
for(unsigned int i=0; i<count; i++) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"resource/gif/1" ofType:@"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:path];
[images addObject:image];
//[images addObject:[_gifFrames objectAtIndex:i]];
}
[animation setValues: images];
//[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
animation.duration = _gifTotalTime;
animation.delegate = self;
/* The repeat count of the object. May be fractional. Defaults to 0. */
animation.repeatCount = 5;
[self.layer addAnimation:animation forKey:@"gifAnimation"];
return YES;
}
- (void) stopGif {
[self.layer removeAllAnimations];
}
- (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
self.layer.contents = nil;
}
//Only override drawRect: if you perform custom drawing. An empty implementation adversely affects performance during animation
- (void) drawRect:(CGRect)rect {
//Drawing code
}
@end
文章来源: blog.csdn.net,作者:福州-司马懿,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/chy555chy/article/details/51703446
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)