Divyesh
Divyesh

Reputation: 2401

How to use gif with UIImageView in Xamarin.iOS without using third party library?

I want to load gif image in UIImageView. I've try to use it wih FLAnimatedImage but it not worked. I have taken imageview in storyboard and added gif to resources.

Upvotes: 1

Views: 1101

Answers (3)

Gustavo Baiocchi Costa
Gustavo Baiocchi Costa

Reputation: 1448

I elaborated from montemagno solution to run from an internal file instead of an url: https://montemagno.com/animated-gif-uiimageview-in-xamarinios/

internal class GifHelper
{
    public static void LoadGif(UIImageView imageview, string gifName, string directoryPath)
    {
        try
        {
            var gifPath = NSBundle.MainBundle.PathForResource(gifName, "gif", directoryPath);

            var data = NSData.FromFile(gifPath);

            var sourceRef = CGImageSource.FromData(data);

            CreateAnimatedImageView(sourceRef, imageview);
        }
        catch (Exception e)
        {
        }
    }

    private static UIImageView CreateAnimatedImageView(CGImageSource imageSource, UIImageView imageView = null)
    {
        if (imageSource == null)
        {
            return null;
        }

        var frameCount = imageSource.ImageCount;

        var frameImages = new List<NSObject>();
        var frameCGImages = new List<CGImage>();
        var frameDurations = new List<double>();

        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>();
        var framePercentageDurationsDouble = new List<double>();
        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.AnimationDiscrete;
        frameAnimation.Values = frameImages.ToArray();
        frameAnimation.Duration = totalFrameDuration;
        frameAnimation.KeyTimes = framePercentageDurations.ToArray();
        frameAnimation.RemovedOnCompletion = true; // End animation after duration, set false to loop

        nint firstFrameWidth = 0;
        nint firstFrameHeight = 0;

        if (frameCGImages.Count > 0)
        {
            var firstFrame = frameCGImages[0];

            firstFrameWidth = firstFrame.Width;
            firstFrameHeight = firstFrame.Height;
        }

        if (imageView == null)
        {
            imageView = new UIImageView(new RectangleF(0.0f, 0.0f, firstFrameWidth, firstFrameHeight));
        }
        else
        {
            imageView.Layer.RemoveAllAnimations();
        }

        imageView.Layer.AddAnimation(frameAnimation, "contents");

        frameAnimation.Dispose();

        // It returns an imageview in case you want to add this to a view programatically
        return imageView;
    }
}

Then you can use it like:

GifHelper.LoadGif(Imageview, "gif_name", "Folder");

Upvotes: 0

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

If you want to load gif image with UIImageView, I find one article that you can take a look:

https://montemagno.com/animated-gif-uiimageview-in-xamarinios/

Upvotes: 2

Saamer
Saamer

Reputation: 5099

If you try to create the gif using individual images, it will be easier, as you can see here. When you convert the native code from here to C#, you get this

UIImageView gifView = new UIImageView();
gifView.AnimationImages = new UIImage[] {
    UIImage.FromBundle("Image1.png"),
    UIImage.FromBundle("Image2.png"),
    UIImage.FromBundle("Image3.png"),
    UIImage.FromBundle("Image4.png")
};
gifView.AnimationRepeatCount = 0; // Repeat forever.
gifView.AnimationDuration = 1.0; // Every 1s.
gifView.StartAnimating();
gifView.View.Frame = new CoreGraphics.CGRect(0, 20, this.View.Bounds.Size.Width, 180); // size of the animation
this.View.AddSubview(gifView);

Upvotes: 1

Related Questions