Add animated Gif image in Iphone UIImageView

I need to load an animated Gif image from a URL in UIImageview.

When I used the normal code, the image didn't load.

Is there any other way to load animated Gif images?

143204 次浏览
UIImageView* animatedImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:@"image1.gif"],
[UIImage imageNamed:@"image2.gif"],
[UIImage imageNamed:@"image3.gif"],
[UIImage imageNamed:@"image4.gif"], nil];
animatedImageView.animationDuration = 1.0f;
animatedImageView.animationRepeatCount = 0;
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];

You can load more than one gif images.

You can split your gif using the following ImageMagick command:

convert +adjoin loading.gif out%d.gif

If you must load the gif image from URL, you can always embed the gif in an image tag in a UIWebView.

This has found an accepted answered, but I recently came across the UIImage+animatedGIF UIImage extension. It provides the following category:

+[UIImage animatedImageWithAnimatedGIFURL:(NSURL *)url]

allowing you to simply:

#import "UIImage+animatedGIF.h"
UIImage* mygif = [UIImage animatedImageWithAnimatedGIFURL:[NSURL URLWithString:@"http://en.wikipedia.org/wiki/File:Rotating_earth_(large).gif"]];

Works like magic.

This doesn't meet the requirement of using a UIImageView, but maybe this would simplify things for you. Have you considered using a UIWebView?

NSString *gifUrl = @"http://gifs.com";
NSURL *url = [NSURL URLWithString: gifUrl];
[webView loadRequest: [NSURLRequest requestWithURL:url]

If you want, instead of linking to a URL that requires Internet, you could import an HTML file into your Xcode project and set the root in the string.

Check this link

https://github.com/mayoff/uiimage-from-animated-gif/blob/master/uiimage-from-animated-gif/UIImage%2BanimatedGIF.h

and import these clases UIImage+animatedGIF.h,UIImage+animatedGIF.m

Use this code

 NSURL *urlZif = [[NSBundle mainBundle] URLForResource:@"dots64" withExtension:@"gif"];
NSString *path=[[NSBundle mainBundle]pathForResource:@"bar180" ofType:@"gif"];
NSURL *url=[[NSURL alloc] initFileURLWithPath:path];
imageVw.image= [UIImage animatedImageWithAnimatedGIFURL:url];

Hope this is helpfull

Here is an interesting library: https://github.com/Flipboard/FLAnimatedImage

I tested the demo example and it's working great. It's a child of UIImageView. So I think you can use it in your Storyboard directly as well.

Cheers

Here is the best solution to use Gif Image. Add SDWebImage from Github in your project.

#import "UIImage+GIF.h"


_imageViewAnimatedGif.image= [UIImage sd_animatedGIFNamed:@"thumbnail"];

SWIFT 3

Here is the update for those who need the Swift version!.

A few days ago i needed to do something like this. I load some data from a server according specific parameters and in the meanwhile i wanted to show a different gif image of "loading". I was looking for an option to do it with an UIImageView but unfortunately i didn't find something to do it without splitting the .gif images. So i decided to implement a solution using a UIWebView and i want to shared it:

extension UIView{
func animateWithGIF(name: String){
let htmlString: String =    "<!DOCTYPE html><html><head><title></title></head>" +
"<body style=\"background-color: transparent;\">" +
"<img src=\""+name+"\" align=\"middle\" style=\"width:100%;height:100%;\">" +
"</body>" +
"</html>"


let path: NSString = Bundle.main.bundlePath as NSString
let baseURL: URL = URL(fileURLWithPath: path as String) // to load images just specifying its name without full path


let frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
let gifView = UIWebView(frame: frame)


gifView.isOpaque = false // The drawing system composites the view normally with other content.
gifView.backgroundColor = UIColor.clear
gifView.loadHTMLString(htmlString, baseURL: baseURL)


var s: [UIView] = self.subviews
for i in 0 ..< s.count {
if s[i].isKind(of: UIWebView.self) { s[i].removeFromSuperview() }
}


self.addSubview(gifView)
}


func animateWithGIF(url: String){
self.animateWithGIF(name: url)
}
}

I made an extension for UIView which adds a UIWebView as subview and displays the .gif images just passing its name.

Now in my UIViewController i have a UIView named 'loadingView' which is my 'loading' indicator and whenever i wanted to show the .gif image, i did something like this:

class ViewController: UIViewController {
@IBOutlet var loadingView: UIView!


override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
configureLoadingView(name: "loading.gif")
}


override func viewDidLoad() {
super.viewDidLoad()
// .... some code
// show "loading" image
showLoadingView()
}


func showLoadingView(){
loadingView.isHidden = false
}
func hideLoadingView(){
loadingView.isHidden = true
}
func configureLoadingView(name: String){
loadingView.animateWithGIF(name: "name")// change the image
}
}

when I wanted to change the gif image, simply called the function configureLoadingView() with the name of my new .gif image and calling showLoadingView(), hideLoadingView() properly everything works fine!.

BUT...

... if you have the image splitted then you can animate it in a single line with a UIImage static method called UIImage.animatedImageNamed like this:

imageView.image = UIImage.animatedImageNamed("imageName", duration: 1.0)

From the docs:

This method loads a series of files by appending a series of numbers to the base file name provided in the name parameter. All images included in the animated image should share the same size and scale.

Or you can make it with the UIImage.animatedImageWithImages method like this:

let images: [UIImage] = [UIImage(named: "imageName1")!,
UIImage(named: "imageName2")!,
...,
UIImage(named: "imageNameN")!]
imageView.image = UIImage.animatedImage(with: images, duration: 1.0)

From the docs:

Creates and returns an animated image from an existing set of images. All images included in the animated image should share the same size and scale.

I know that an answer has already been approved, but its hard not to try to share that I've created an embedded framework that adds Gif support to iOS that feels just like if you were using any other UIKit Framework class.

Here's an example:

UIGifImage *gif = [[UIGifImage alloc] initWithData:imageData];
anUiImageView.image = gif;

Download the latest release from https://github.com/ObjSal/UIGifImage/releases

-- Sal

You Can use https://github.com/Flipboard/FLAnimatedImage

#import "FLAnimatedImage.h"
NSData *dt=[NSData dataWithContentsOfFile:path];
imageView1 = [[FLAnimatedImageView alloc] init];
FLAnimatedImage *image1 = [FLAnimatedImage animatedImageWithGIFData:dt];
imageView1.animatedImage = image1;
imageView1.frame = CGRectMake(0, 5, 168, 80);
[self.view addSubview:imageView1];

Swift 3:

As suggested above I'm using FLAnimatedImage with an FLAnimatedImageView. And I'm loading the gif as a data set from xcassets. This allows me to provide different gifs for iphone and ipad for appearance and app slicing purposes. This is far more performant than anything else I've tried. It's also easy to pause using .stopAnimating().

if let asset = NSDataAsset(name: "animation") {
let gifData = asset.data
let gif = FLAnimatedImage(animatedGIFData: gifData)
imageView.animatedImage = gif
}

If you don't want to use 3rd party library,

extension UIImageView {
func setGIFImage(name: String, repeatCount: Int = 0 ) {
DispatchQueue.global().async {
if let gif = UIImage.makeGIFFromCollection(name: name, repeatCount: repeatCount) {
DispatchQueue.main.async {
self.setImage(withGIF: gif)
self.startAnimating()
}
}
}
}


private func setImage(withGIF gif: GIF) {
animationImages = gif.images
animationDuration = gif.durationInSec
animationRepeatCount = gif.repeatCount
}
}


extension UIImage {
class func makeGIFFromCollection(name: String, repeatCount: Int = 0) -> GIF? {
guard let path = Bundle.main.path(forResource: name, ofType: "gif") else {
print("Cannot find a path from the file \"\(name)\"")
return nil
}


let url = URL(fileURLWithPath: path)
let data = try? Data(contentsOf: url)
guard let d = data else {
print("Cannot turn image named \"\(name)\" into data")
return nil
}


return makeGIFFromData(data: d, repeatCount: repeatCount)
}


class func makeGIFFromData(data: Data, repeatCount: Int = 0) -> GIF? {
guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
print("Source for the image does not exist")
return nil
}


let count = CGImageSourceGetCount(source)
var images = [UIImage]()
var duration = 0.0


for i in 0..<count {
if let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) {
let image = UIImage(cgImage: cgImage)
images.append(image)


let delaySeconds = UIImage.delayForImageAtIndex(Int(i),
source: source)
duration += delaySeconds
}
}


return GIF(images: images, durationInSec: duration, repeatCount: repeatCount)
}


class func delayForImageAtIndex(_ index: Int, source: CGImageSource!) -> Double {
var delay = 0.0


// Get dictionaries
let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
let gifPropertiesPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 0)
if CFDictionaryGetValueIfPresent(cfProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque(), gifPropertiesPointer) == false {
return delay
}


let gifProperties:CFDictionary = unsafeBitCast(gifPropertiesPointer.pointee, to: CFDictionary.self)


// Get delay time
var delayObject: AnyObject = unsafeBitCast(
CFDictionaryGetValue(gifProperties,
Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()),
to: AnyObject.self)
if delayObject.doubleValue == 0 {
delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties,
Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self)
}


delay = delayObject as? Double ?? 0


return delay
}
}


class GIF: NSObject {
let images: [UIImage]
let durationInSec: TimeInterval
let repeatCount: Int


init(images: [UIImage], durationInSec: TimeInterval, repeatCount: Int = 0) {
self.images = images
self.durationInSec = durationInSec
self.repeatCount = repeatCount
}
}

To use,

override func viewDidLoad() {
super.viewDidLoad()
imageView.setGIFImage(name: "gif_file_name")
}


override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
imageView.stopAnimating()
}

Make sure you add the gif file in the project, not in the .xcassets folder.

With Swift and KingFisher

   lazy var animatedPart: AnimatedImageView = {
let img = AnimatedImageView()
if let src = Bundle.main.url(forResource: "xx", withExtension: "gif"){
img.kf.setImage(with: src)
}
return img
}()