在 iOS 中显示动画 GIF

我注意到,通过 iMessage,可以发送和显示动画 gif。这是否意味着苹果现在支持在应用程序中显示动画 GIF,或者是最简单的方法仍然是将图像分割成帧,然后按顺序显示它们?在 iOS5.1中显示动画 GIF 最简单的方法是什么?

谢谢!

113767 次浏览

I would recommend using the following code, it's much more lightweight, and compatible with ARC and non-ARC project, it adds a simple category on UIImageView:

https://github.com/mayoff/uiimage-from-animated-gif/

#import <QuickLook/QuickLook.h>
#import "ViewController.h"


@implementation ViewController


- (void)viewDidLoad
{
[super viewDidLoad];


QLPreviewController *preview = [[QLPreviewController alloc] init];
preview.dataSource = self;


[self addChildViewController:preview];
[self.view addSubview:preview.view];
}


#pragma mark - QLPreviewControllerDataSource


- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController
{
return 1;
}


- (id)previewController:(QLPreviewController *)previewController previewItemAtIndex:(NSInteger)idx
{
NSURL *fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"myanimated.gif" ofType:nil]];
return fileURL;
}


@end

If you are targeting iOS7 and already have the image split into frames you can use animatedImageNamed:duration:.

Let's say you are animating a spinner. Copy all of your frames into the project and name them as follows:

  • spinner-1.png
  • spinner-2.png
  • spinner-3.png
  • etc.,

Then create the image via:

[UIImage animatedImageNamed:@"spinner-" duration:1.0f];

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. For example, if the name parameter had ‘image’ as its contents, this method would attempt to load images from files with the names ‘image0’, ‘image1’ and so on all the way up to ‘image1024’. All images included in the animated image should share the same size and scale.

Another alternative is to use a UIWebView to display the animated GIF. If the GIF is going to be fetched from a server, then this takes care of the fetching. It also works with local GIFs.

FLAnimatedImage is a performant open source animated GIF engine for iOS:

  • Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers
  • Honors variable frame delays
  • Behaves gracefully under memory pressure
  • Eliminates delays or blocking during the first playback loop
  • Interprets the frame delays of fast GIFs the same way modern browsers do

It's a well-tested component that I wrote to power all GIFs in Flipboard.

From iOS 11 Photos framework allows to add animated Gifs playback.

Sample app can be dowloaded here

More info about animated Gifs playback (starting from 13:35 min): https://developer.apple.com/videos/play/wwdc2017/505/

enter image description here

You can use SwiftGif from this link

Usage:

imageView.loadGif(name: "jeremy")
NSString *pathForGif = [[NSBundle mainBundle] pathForResource:@"ic_homepage_random0330" ofType: @"gif"];


NSData *gifData = [NSData dataWithContentsOfFile:pathForGif];
                

YYImage *img = [YYImage imageWithData:gifData];


YYAnimatedImageView *contentImageView = [[YYAnimatedImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
contentImageView.autoPlayAnimatedImage = YES;
contentImageView.image = img;

In 2021, splitting gif into individual frames is still a valid solution.

Here is the accepted answer adapted to Swift:

  1. Split your gif into individual frames using an online service like ezygif: https://ezgif.com/split/ Make sure to export them as .png.

  2. Create an xcassets arhcive and create an asset for each frame. Make sure that the difference is just the suffix which should be a number for each frame of the gif (i.e. animated-image-1, animaged-image-2, etc) I'm using a single scale to make it easier.

  3. Load it up into an image view:

final class AnimatedImage: UIImageView {
init() {
super.init(frame: .zero)


let animatedImage = UIImage.animatedImageNamed("animated-image-", duration: 0.3)
translatesAutoresizingMaskIntoConstraints = false
image = animatedImage


NSLayoutConstraint.activate([
widthAnchor.constraint(equalToConstant: 150),
heightAnchor.constraint(equalTo: widthAnchor)
])
}


required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}