Agregar imagen GIF animada en Iphone UIImageView

Respuestas:

138
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];

Puede cargar más de una imagen gif.

Puedes dividir tu gif usando el siguiente comando ImageMagick :

convert +adjoin loading.gif out%d.gif
Ishu
fuente
1
Necesito cargar la imagen de la siguiente URL en UIImageview .... feedads.g.doubleclick.net/~at/K_fHnmr7a7T0pru2TjQC29TsPYY/1/di
Velmurugan
NSData * mydata = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: myurl]]; UIImage * myimage = [[UIImage alloc] initWithData: imageData]; use esto para leer desde la URL y luego agregue este objeto a la matriz
Ishu
8
El iPhone OS no puede mostrar y no mostrará correctamente las imágenes GIF animadas. El objeto UIImage no se puede utilizar para esto. Aunque admite imágenes GIF, cualquier animación se descartará y solo se mostrará el primer fotograma. Entonces, si necesita mostrar un GIF animado dentro de una aplicación de iPhone, está jodido. El código debe escribirse ... Eche un vistazo aquí: pliep.nl/blog/2009/04/…
fyasar
10
Solo necesita usar la vista web en lugar de la vista de imágenes
Shreesh Garg
2
github.com/mayoff/uiimage-from-animated-gif simplemente use esta Categoría, ya que hace que todo lo descrito en la respuesta sea automático
Michael
53

Esto ha encontrado una respuesta aceptada, pero recientemente encontré la extensión UIImage + animatedGIF UIImage. Proporciona la siguiente categoría:

+[UIImage animatedImageWithAnimatedGIFURL:(NSURL *)url]

permitiéndote simplemente:

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

Funciona como magia.

Dom Vinyard
fuente
1
¿Habría alguna forma de usar un archivo directamente en el proyecto en lugar de cargar el gif desde una URL?
juliensaad
2
UIImage + animatedGIF ... una de las mejores categorías que he visto ... gracias @robmayoff
whyoz
22

Aquí está la mejor solución para usar Gif Image. Agregue SDWebImage de Github en su proyecto.

#import "UIImage+GIF.h"

_imageViewAnimatedGif.image= [UIImage sd_animatedGIFNamed:@"thumbnail"];
Arvind Kumar
fuente
Esto es exactamente lo que estaba buscando. ¡Gracias hombre! Si puedo agregar algo: el UIImageView no está sintetizado, pero debe crearse en el guión gráfico y vincularse a su IBOutlet :)
Lucia Belardinelli
12

Revisa este enlace

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

e importar estas clases UIImage + animatedGIF.h, UIImage + animatedGIF.m

Usa este código

 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];

Espero que esto sea útil

Mohit
fuente
8

Si no desea utilizar la biblioteca de terceros,

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
    }
}

Usar,

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

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

Asegúrese de agregar el archivo gif en el proyecto, no en la carpeta .xcassets.

Sukwon
fuente
Su código incluye: Hilo 1: EXC_BAD_INSTRUCTION (código = EXC_I386_INVOP, subcódigo = 0x0) ¡error!
Codificador ACJHP
5

Esto no cumple con el requisito de usar un UIImageView, pero tal vez esto simplificaría las cosas para usted. ¿Ha considerado utilizar UIWebView?

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

Si lo desea, en lugar de vincular a una URL que requiera Internet, puede importar un archivo HTML a su proyecto Xcode y establecer la raíz en la cadena.

trevorgrayson
fuente
3

Aquí hay una biblioteca interesante: https://github.com/Flipboard/FLAnimatedImage

Probé el ejemplo de demostración y está funcionando muy bien. Es un hijo de UIImageView. Así que creo que también puedes usarlo directamente en tu Storyboard.

Salud

akdesarrollador
fuente
3

Sé que ya se aprobó una respuesta, pero es difícil no intentar compartir que he creado un marco integrado que agrega compatibilidad con Gif para iOS que se siente como si estuviera usando cualquier otra clase de marco UIKit.

He aquí un ejemplo:

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

Descargue la última versión de https://github.com/ObjSal/UIGifImage/releases

- Sal

ObjSal
fuente
1

Si debe cargar la imagen gif desde la URL, siempre puede incrustar el gif en una etiqueta de imagen en un archivo UIWebView.

jd.
fuente
1

SWIFT 3

¡Aquí está la actualización para aquellos que necesitan la versión Swift !.

Hace unos días necesitaba hacer algo como esto. Cargo algunos datos de un servidor según parámetros específicos y mientras tanto quería mostrar una imagen gif diferente de "cargando". Estaba buscando una opción para hacerlo con un UIImageViewpero desafortunadamente no encontré nada para hacerlo sin dividir las imágenes .gif. Entonces decidí implementar una solución usando a UIWebViewy quiero compartirla:

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)
    }
} 

Hice una extensión para la UIViewque agrega una UIWebViewsubvista as y muestra las imágenes .gif simplemente pasando su nombre.

Ahora en mi UIViewControllertengo un UIView'loadingView' llamado que es mi indicador de 'carga' y cada vez que quería mostrar la imagen .gif, hacía algo como esto:

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
    }
}

cuando quise cambiar la imagen gif, simplemente llamé a la función configureLoadingView()con el nombre de mi nueva imagen .gif y llamé showLoadingView(),hideLoadingView() correctamente todo funciona bien !.

PERO...

... si tiene la imagen dividida, puede animarla en una sola línea con un UIImagemétodo estático llamado UIImage.animatedImageNamedasí:

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

De los documentos:

Este método carga una serie de archivos agregando una serie de números al nombre del archivo base proporcionado en el parámetro de nombre. Todas las imágenes incluidas en la imagen animada deben compartir el mismo tamaño y escala.

O puedes hacerlo con el UIImage.animatedImageWithImagesmétodo como este:

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

De los documentos:

Crea y devuelve una imagen animada a partir de un conjunto de imágenes existente. Todas las imágenes incluidas en la imagen animada deben compartir el mismo tamaño y escala.

mauricioconde
fuente
0

Puede usar 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];
atul awasthi
fuente
0

Swift 3:

Como se sugirió anteriormente, estoy usando FLAnimatedImage con un FLAnimatedImageView. Y estoy cargando el gif como un conjunto de datos de xcassets. Esto me permite proporcionar diferentes gifs para iphone y ipad con fines de apariencia y división de aplicaciones. Esto es mucho más eficaz que cualquier otra cosa que haya probado. También es fácil pausar usando .stopAnimating ().

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

Con Swift y 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
   }()
Perla Negra
fuente