Dodaj animowany obraz Gif w Iphone UIImageView

80

Muszę załadować animowany obraz Gif z adresu URL w UIImageview.

Kiedy użyłem normalnego kodu, obraz się nie załadował.

Czy jest jakiś inny sposób ładowania animowanych obrazów Gif?

Velmurugan
źródło
Muszę załadować obraz z następującego adresu URL w UIImageview .... feedads.g.doubleclick.net/~at/K_fHnmr7a7T0pru2TjQC29TsPYY/1/di
Velmurugan
Przejść przez ten link do SWIFT: stackoverflow.com/questions/27919620/...
Mr.Javed Multani

Odpowiedzi:

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

Możesz załadować więcej niż jeden obraz GIF.

Możesz podzielić swój gif za pomocą następującego polecenia ImageMagick :

convert +adjoin loading.gif out%d.gif
Ishu
źródło
1
Muszę załadować obraz z następującego adresu URL w UIImageview .... feedads.g.doubleclick.net/~at/K_fHnmr7a7T0pru2TjQC29TsPYY/1/di
Velmurugan
NSData * mydata = [[przydzielenie NSData] initWithContentsOfURL: [NSURL URLWithString: myurl]]; UIImage * myimage = [[UIImage assign] initWithData: imageData]; użyj tego do odczytu z
adresu
8
System operacyjny iPhone nie może i nie wyświetla poprawnie animowanych obrazów GIF. Nie można do tego użyć obiektu UIImage. Mimo że obsługuje obrazy GIF, każda animacja zostanie odrzucona i zostanie wyświetlona tylko pierwsza klatka. Tak więc, jeśli chcesz wyświetlić animowany GIF w aplikacji na iPhone'a, masz przerąbane. Kod musi zostać napisany ... Spójrz tutaj: pliep.nl/blog/2009/04/…
fyasar
10
Wystarczy użyć widoku internetowego zamiast widoku obrazu
Shreesh Garg
2
github.com/mayoff/uiimage-from-animated-gif po prostu użyj tej kategorii, ponieważ automatycznie sprawia, że ​​wszystko opisane w odpowiedzi jest automatycznie
Michael
53

To znalazło akceptowaną odpowiedź, ale ostatnio natknąłem się na rozszerzenie UIImage + animatedGIF UIImage. Zapewnia następującą kategorię:

+[UIImage animatedImageWithAnimatedGIFURL:(NSURL *)url]

co pozwala po prostu:

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

Działa jak magia.

Dom Vinyard
źródło
1
Czy byłby sposób na użycie pliku bezpośrednio w projekcie zamiast ładowania gif z adresu URL?
juliensaad
2
UIImage + animatedGIF ... jedna z najlepszych kategorii, jakie kiedykolwiek widziałem ... dzięki @robmayoff
whyoz
22

Oto najlepsze rozwiązanie do korzystania z obrazu Gif. Dodaj SDWebImage z Github do swojego projektu.

#import "UIImage+GIF.h"

_imageViewAnimatedGif.image= [UIImage sd_animatedGIFNamed:@"thumbnail"];
Arvind Kumar
źródło
To jest dokładnie to, czego szukałem. Dziękuje! Jeśli mogę coś dodać: UIImageView nie jest syntetyzowany, ale powinien zostać utworzony w storyboardzie i połączony z jego IBOutletem :)
Lucia Belardinelli
12

Sprawdź ten link

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

i zaimportuj te klasy UIImage + animatedGIF.h, UIImage + animatedGIF.m

Użyj tego kodu

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

Mam nadzieję, że to jest pomocne

Mohit
źródło
8

Jeśli nie chcesz korzystać z biblioteki innej firmy,

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

Używać,

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

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

Upewnij się, że dodajesz plik gif do projektu, a nie do folderu .xcassets.

Sukwon
źródło
Twój kod wskazuje: Wątek 1: EXC_BAD_INSTRUCTION (kod = EXC_I386_INVOP, subkod = 0x0) błąd!
Coder ACJHP
5

Nie spełnia to wymagań korzystania z UIImageView, ale może to uprościłoby sprawę. Czy rozważałeś użycie UIWebView?

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

Jeśli chcesz, zamiast łączyć się z adresem URL, który wymaga Internetu, możesz zaimportować plik HTML do projektu Xcode i ustawić katalog główny w ciągu.

trevorgrayson
źródło
3

Oto interesująca biblioteka: https://github.com/Flipboard/FLAnimatedImage

Przetestowałem przykład demo i działa świetnie. Jest to element potomny UIImageView. Myślę więc, że możesz go również użyć bezpośrednio w swoim Storyboard.

Twoje zdrowie

akdeveloper
źródło
3

Wiem, że odpowiedź została już zatwierdzona, ale trudno nie spróbować podzielić się tym, że stworzyłem wbudowany framework, który dodaje obsługę Gif do iOS, który wygląda tak, jakbyś używał innej klasy UIKit Framework.

Oto przykład:

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

Pobierz najnowszą wersję z https://github.com/ObjSal/UIGifImage/releases

- Sal

ObjSal
źródło
1

Jeśli musisz załadować obraz gif z adresu URL, zawsze możesz osadzić gif w tagu obrazu w pliku UIWebView.

jd.
źródło
1

SWIFT 3

Oto aktualizacja dla tych, którzy potrzebują wersji Swift !.

Kilka dni temu musiałem zrobić coś takiego. Ładuję dane z serwera według określonych parametrów, aw międzyczasie chciałem pokazać inny obraz gif „wczytywania”. Szukałem opcji zrobienia tego za pomocą pliku, UIImageViewale niestety nie znalazłem czegoś, co mogłoby to zrobić bez podzielenia obrazów .gif. Postanowiłem więc wdrożyć rozwiązanie za pomocą UIWebViewa i chcę się nim podzielić:

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

Zrobiłem rozszerzenie, UIViewktóre dodaje UIWebViewwidok podrzędny as i wyświetla obrazy .gif, przekazując tylko jego nazwę.

Teraz w moim UIViewControllermam UIViewnazwany `` loadingView '', który jest moim wskaźnikiem `` ładowania '' i kiedykolwiek chciałem wyświetlić obraz .gif, zrobiłem coś takiego:

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

kiedy chciałem zmienić obraz gif, po prostu wywołałem funkcję configureLoadingView()z nazwą mojego nowego obrazu .gif i wywołałem showLoadingView(), hideLoadingView()wszystko działa dobrze !.

ALE...

... jeśli masz podzielony obraz, możesz go animować w pojedynczej linii za pomocą UIImagestatycznej metody o nazwie UIImage.animatedImageNamed:

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

Z dokumentów:

Ta metoda ładuje serię plików, dołączając serię liczb do podstawowej nazwy pliku podanej w parametrze name. Wszystkie obrazy zawarte w animowanym obrazie powinny mieć ten sam rozmiar i skalę.

Lub możesz to zrobić za pomocą takiej UIImage.animatedImageWithImagesmetody:

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

Z dokumentów:

Tworzy i zwraca animowany obraz z istniejącego zestawu obrazów. Wszystkie obrazy zawarte w animowanym obrazie powinny mieć ten sam rozmiar i skalę.

mauricioconde
źródło
0

Możesz użyć 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
źródło
0

Swift 3:

Jak zasugerowano powyżej, używam FLAnimatedImage z FLAnimatedImageView. Ładuję gif jako zestaw danych z xcassets. Dzięki temu mogę udostępniać różne gify na iPhone'a i iPada do celów związanych z wyglądem i fragmentowaniem aplikacji. To jest o wiele bardziej wydajne niż cokolwiek innego, czego próbowałem. Można też łatwo wstrzymać pracę za pomocą .stopAnimating ().

if let asset = NSDataAsset(name: "animation") {
    let gifData = asset.data
    let gif = FLAnimatedImage(animatedGIFData: gifData)
    imageView.animatedImage = gif
  }
Matt Bearson
źródło
0

Z Swift i 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
   }()
czarna Perła
źródło