Skip to content

Instantly share code, notes, and snippets.

@jamesmontemagno
Last active November 30, 2023 12:29
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jamesmontemagno/7619563 to your computer and use it in GitHub Desktop.
Save jamesmontemagno/7619563 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.Drawing;
using MonoTouch.CoreAnimation;
using MonoTouch.CoreGraphics;
using MonoTouch.Foundation;
using MonoTouch.ImageIO;
using MonoTouch.UIKit;
namespace PuppyKittyOverflow.Touch
{
public class AnimatedImageView
{
public static UIImageView GetAnimatedImageView(string url, UIImageView imageView = null)
{
var sourceRef = CGImageSource.FromUrl(NSUrl.FromString(url));
return CreateAnimatedImageView (sourceRef, imageView);
}
public static UIImageView GetAnimatedImageView(NSData nsData, UIImageView imageView = null)
{
var sourceRef = CGImageSource.FromData(nsData);
return CreateAnimatedImageView(sourceRef, imageView);
}
private static UIImageView CreateAnimatedImageView(CGImageSource imageSource, UIImageView imageView = null)
{
var frameCount = imageSource.ImageCount;
var frameImages = new List<NSObject>(frameCount);
var frameCGImages = new List<CGImage>(frameCount);
var frameDurations = new List<double>(frameCount);
var totalFrameDuration = 0.0;
for (int i = 0; i < frameCount; i++)
{
var frameImage = imageSource.CreateImage(i, null);
frameCGImages.Add(frameImage);
frameImages.Add(NSObject.FromObject(frameImage));
var properties = imageSource.GetProperties(i, null);
var duration = properties.Dictionary["{GIF}"];
var delayTime = duration.ValueForKey(new NSString("DelayTime"));
duration.Dispose ();
var realDuration = double.Parse(delayTime.ToString());
frameDurations.Add(realDuration);
totalFrameDuration += realDuration;
frameImage.Dispose ();
}
var framePercentageDurations = new List<NSNumber>(frameCount);
var framePercentageDurationsDouble = new List<double>(frameCount);
NSNumber currentDurationPercentage = 0.0f;
double currentDurationDouble = 0.0f;
for (int i = 0; i < frameCount; i++)
{
if (i != 0)
{
var previousDuration = frameDurations[i - 1];
var previousDurationPercentage = framePercentageDurationsDouble[i - 1];
var number = previousDurationPercentage + (previousDuration/totalFrameDuration);
currentDurationDouble = number;
currentDurationPercentage = new NSNumber(number);
}
framePercentageDurationsDouble.Add(currentDurationDouble);
framePercentageDurations.Add(currentDurationPercentage);
}
var imageSourceProperties = imageSource.GetProperties(null);
var imageSourceGIFProperties = imageSourceProperties.Dictionary["{GIF}"];
var loopCount = imageSourceGIFProperties.ValueForKey(new NSString("LoopCount"));
var imageSourceLoopCount = float.Parse(loopCount.ToString());
var frameAnimation = new CAKeyFrameAnimation();
frameAnimation.KeyPath = "contents";
if (imageSourceLoopCount <= 0.0f)
{
frameAnimation.RepeatCount = float.MaxValue;
}
else
{
frameAnimation.RepeatCount = imageSourceLoopCount;
}
imageSourceGIFProperties.Dispose ();
frameAnimation.CalculationMode = CAAnimation.AnimationDescrete;
frameAnimation.Values = frameImages.ToArray();
frameAnimation.Duration = totalFrameDuration;
frameAnimation.KeyTimes = framePercentageDurations.ToArray();
frameAnimation.RemovedOnCompletion = false;
var firstFrame = frameCGImages[0];
if(imageView == null)
imageView = new UIImageView(new RectangleF(0.0f, 0.0f, firstFrame.Width, firstFrame.Height));
else
imageView.Layer.RemoveAllAnimations();
imageView.Layer.AddAnimation(frameAnimation, "contents");
frameAnimation.Dispose ();
return imageView;
}
}
}
var client = new HttpClient();
var stream = await client.GetStreamAsync(image);
var data = await GetDataAsync(stream);
AnimatedImageView.GetAnimatedImageView(data, ImageViewAnimal);
private async Task<NSData> GetDataAsync(Stream stream)
{
return await Task.Run (() => {return NSData.FromStream (stream);});
}
@fnk0
Copy link

fnk0 commented Jul 22, 2015

Hi, first of all thanks for this gist!! I do have one question tough... is there any reasons you can think about why this is not working on a iPad 2? It works fine on a emulator and a iPad mini, but it does not work on a iPad 2 :(

@JorgeMadson
Copy link

How can i use it for local files? Can someone put this in a git hub project?

@lbulegato
Copy link

Be aware that this class leads to very huge memory leaks.
CGImage is not memory managed and if you don't manually remove the animateView the memory continues to increase without any limit.
You can easily see this with the apple profiler

@umeshkamble
Copy link

Hi, If you are looking same implementation in MAUI. Please visit below GitHub link

Gif Animation in iOS

@ledwardsfoodzee
Copy link

Be aware that this class leads to very huge memory leaks. CGImage is not memory managed and if you don't manually remove the animateView the memory continues to increase without any limit. You can easily see this with the apple profiler

I have jus learnt this after 3 days of troubleshooting !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment