Display Animated GIF
Asked Answered
I

29

270

I want to display animated GIF images in my aplication. As I found out the hard way Android doesn't support animated GIF natively.

However it can display animations using AnimationDrawable:

Develop > Guides > Images & Graphics > Drawables Overview

The example uses animation saved as frames in application resources but what I need is to display animated gif directly.

My plan is to break animated GIF to frames and add each frame as drawable to AnimationDrawable.

Does anyone know how to extract frames from animated GIF and convert each of them into Drawable?

Inbred answered 7/9, 2010 at 15:42 Comment(6)
Do you mean within android , or extracting frames from a gif with an external tool?Disintegrate
it definitely is a bug, see IssueTracker for more information.Puttergill
Just for all those who came here by searching for an app that can display animated GIFs: quickPicAaren
#30338758Kev
Use fresco to display GIF github.com/facebook/fresco I think this is a simple solution.Margarita
I was looking for that question and found a solution at: play GIF inside android applicationCostive
R
193

Android actually can decode and display animated GIFs, using android.graphics.Movie class.

This is not too much documented, but is in SDK Reference. Moreover, it is used in Samples in ApiDemos in BitmapDecode example with some animated flag.

Rhinarium answered 14/10, 2011 at 18:48 Comment(12)
How stable is this? I have implemented it in my app, on my Ice Cream Sandwich device it is not working at all, on a 2.3 emulator it is working but some of the GIF frames are buggy (wrong colors). On a computer it is of course working fine. What gives?Housecoat
@Bicou On post-HC devices you should setLayerType(LAYER_TYPE_SOFTWARE) on your View. But it still only works for some gifs and for some devices.Flemming
@MichałK Thank you! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p); worked!Fustic
I'm afraid that mMovie.draw crashes with a segfault if android:hardwareAccelerated="false" is not set on the activity in the manifest.Rambow
@lubosz: LAYER_TYPE_SOFTWARE should be enough to set.Rhinarium
Movie doesn't appear to support animated gifs with delta frames (and transparency) until Android OS 4.x. On earlier versions it will display garbage.Mev
Movie class is undocumented on purpose - it's weak and unsupported. If you need proper Gif animations, you better implement it yourself. I did it for my app using NDK.Rhinarium
Check this well implemented library out: github.com/sbakhtiarov/gif-movie-viewJulianejuliann
please help me with this: #32997378Kerstin
Could the link in Samples in ApiDemos in BitmapDecode be changed to this one? Based on the comments, it seems to be similar and this one is a live link ( as for the date of this comment ).Sile
Link is dead. Use this one: BitmapDecodeDirge
This class was deprecated in API level 28. Prefer AnimatedImageDrawablePertussis
V
74

UPDATE:

Use glide:

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.9.0'
}

usage:

Glide.with(context).load(GIF_URI).into(new DrawableImageViewTarget(IMAGE_VIEW));

see docs

Villeneuve answered 26/7, 2015 at 17:14 Comment(7)
Looks OK to me now, obviously the answer can't include the whole library, so the call example seems enough.Bein
@Bein Obviously the code wasn't included at the time of the flagging.Disconsider
I don't recommend using this library if you're already using the NDK. After adding this lib to gradle, a Unity module stopped working.Listen
This is the best library I have found. One thing that I am stuck in is implementing pinch to zoom the gif image. Does anybody know?Cosmos
GlideDrawableImageViewTarget no longer seems to be availablePantaloons
On glide 4.9.0+ GlideDrawableImageViewTarget is no longer available. Please replace it with DrawableImageViewTargetAstto
@FedericoDeGioannini tnx. updateVilleneuve
C
28

also put (main/assets/htmls/name.gif) [with this html adjust to the size]

<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>

declare in your Xml for example like this (main/res/layout/name.xml): [you define the size, for example]

<WebView
android:layout_width="70dp"
android:layout_height="70dp"
android:id="@+id/webView"
android:layout_gravity="center_horizontal" />

in your Activity put the next code inside of onCreate

web = (WebView) findViewById(R.id.webView); 
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///android_asset/htmls/name.html");

if you want load dynamically you have to load the webview with data:

// or "[path]/name.gif" (e.g: file:///android_asset/name.gif for resources in asset folder), and in loadDataWithBaseURL(), you don't need to set base URL, on the other hand, it's similar to loadData() method.
String gifName = "name.gif";
String yourData = "<html style=\"margin: 0;\">\n" +
        "    <body style=\"margin: 0;\">\n" +
        "    <img src=" + gifName + " style=\"width: 100%; height: 100%\" />\n" +
        "    </body>\n" +
        "    </html>";
// Important to add this attribute to webView to get resource from outside.
webView.getSettings().setAllowFileAccess(true);

// Notice: should use loadDataWithBaseURL. BaseUrl could be the base url such as the path to asset folder, or SDCard or any other path, where your images or the other media resides related to your html
webView.loadDataWithBaseURL("file:///android_asset/", yourData, "text/html", "utf-8", null);
// Or if you want to load image from SD card or where else, here is the idea.
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
webView.loadDataWithBaseURL(base + '/', yourData, "text/html", "utf-8", null);

suggestion: is better load gif with static images for more information check https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

That's it, I hope you help.

Currently we can use Glide https://github.com/bumptech/glide

Contrary answered 15/5, 2015 at 22:25 Comment(6)
If I want to load GIF from sdcard ?Kristianson
if you want to load from sdcard: replace "file:///android_asset/htmls/name.html" for the uri of your imageContrary
Using this method, how can I change the name of the gif file dynamically? I don't want to make an html file to go with every gif I need to display in my appJuliennejuliet
Webview for a GIF?!? Did you think about performance, memory consumption and battery?Mitch
@Mitch that was 5 years ago, currently we can use glide for exampleContrary
insane. using webview as animated imageview or font change in textview... sorry for reaction...Lupercalia
I
22

I solved the problem by splitting gif animations into frames before saving it to phone, so I would not have to deal with it in Android.

Then I download every frame onto phone, create Drawable from it and then create AnimationDrawable - very similar to example from my question

Inbred answered 1/10, 2010 at 18:14 Comment(1)
Which is the documented way of handling animations.Marcello
M
17

i found a very easy way, with a nice and simple working example here

display animated widget

Before getting it working there are some chages to do do in the code

IN THE FOLLOWING

    @Override
    public void onCreate(Bundle savedInstanceState){    
        super.onCreate(savedInstanceStated);   
        setContentView(new MYGIFView());
    }    
}

just replace

setContentView(new MYGIFView());

in

setContentView(new MYGIFView(this));

AND IN

public GIFView(Context context) {
    super(context);

Provide your own gif animation file

    is = context.getResources().openRawResource(R.drawable.earth);
    movie = Movie.decodeStream(is);
}

REPLACE THE FIRST LINE IN

public MYGIFView(Context context) {

according to the name of the class...

after done this little changes it should work as for me...

hope this help

Mahler answered 16/10, 2011 at 14:40 Comment(3)
On which android version you tried this? I tried on android version 2.2 and 2.3 but it returns Movie object null. Any idea of what can be wrong?Sheath
Please clean up this answer, its so, random.Notification
what is the problem with the answer? I just provided a link and some needed fix to get it workingMahler
F
16

Glide 4.6

1. To Load gif

GlideApp.with(context)
            .load(R.raw.gif) // or url
            .into(imageview);

2. To get the file object

GlideApp.with(context)
                .asGif()
                .load(R.raw.gif) //or url
                .into(new SimpleTarget<GifDrawable>() {
                    @Override
                    public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {

                        resource.start();
                      //resource.setLoopCount(1);
                        imageView.setImageDrawable(resource);
                    }
                });
Fling answered 25/2, 2018 at 8:56 Comment(0)
A
10

Ways to show animated GIF on Android:

  • Movie class. As mentioned above, it's fairly buggy.
  • WebView. It's very simple to use and usually works. But sometimes it starts to misbehave, and it's always on some obscure devices you don't have. Plus, you can’t use multiple instances in any kind of list views, because it does things to your memory. Still, you might consider it as a primary approach.
  • Custom code to decode gifs into bitmaps and show them as Drawable or ImageView. I'll mention two libraries:

https://github.com/koral--/android-gif-drawable - decoder is implemented in C, so it's very efficient.

https://code.google.com/p/giffiledecoder - decoder is implemented in Java, so it's easier to work with. Still reasonably efficient, even with large files.

You'll also find many libraries based on GifDecoder class. That's also a Java-based decoder, but it works by loading the entire file into memory, so it's only applicable to small files.

Adoree answered 10/1, 2015 at 15:14 Comment(0)
P
10

I had a really hard time to have animated gif working in Android. I only had following two working:

  1. WebView
  2. Ion

WebView works OK and really easy, but the problem is it makes the view loads slower and the app would be unresponsive for a second or so. I did not like that. So I have tried different approaches (DID NOT WORK):

  1. ImageViewEx is deprecated!
  2. picasso did not load animated gif
  3. android-gif-drawable looks great, but it caused some wired NDK issues in my project. It caused my local NDK library stop working, and I was not able to fix it

I had some back and forth with Ion; Finally, I have it working, and it is really fast :-)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///android_asset/animated.gif");
Paraphrast answered 28/6, 2015 at 11:54 Comment(2)
I had the same NDK related issues with android-gif-drawable.Listen
Hello @RominaV, Have you used progress bar in Ion when load gif, because i need to show progress when load gif.Sayed
M
9

Glide

Image Loader Library for Android, recommended by Google.

  • Glide is quite similar to Picasso but this is much faster than Picasso.
  • Glide consumes less memory than Picasso.

What that Glide has but Picasso doesn't

An ability to load GIF Animation to a simple ImageView might be the most interesting feature of Glide. And yes, you can't do that with Picasso. enter image description here Some important links-

  1. https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
Marmawke answered 12/2, 2016 at 13:10 Comment(3)
Where does Google recommend Glid?Lille
See this, where Developer Android team used the Glide in their sample app. developer.android.com/samples/XYZTouristAttractions/Application/…Marmawke
'Glide is quite similar to Picasso but this is much faster than Picasso' and 'Glide consumes less memory than Picasso.' Sorry I'm not content with these ideas, please prefer to this link: medium.com/@multidots/glide-vs-picasso-930eed42b81d. Btw, I'm can't test Glide 4.0 now because of being not able to upgrade build to 3.0.1 (slow Internet connection); but I did test Glide 3.5.2 on showing gif, it works but not perfectly as I expected on large img (it's flickering), and this is a common issue also. Please CMIW.Timber
P
7

Use ImageViewEx, a library that makes using a gif as easy as using an ImageView.

Profiteer answered 14/8, 2013 at 2:52 Comment(3)
This has been deprecatedApelles
I've looked through this libraries code, it should be good for 2 or so more years.Profiteer
Yes, I think it's relatively fine, just pointing up that the author has decided to deprecate it. (and therefore not maintain it), pointing that we should use something like Picasso, which is weird, because Picasso is an image downloader and won't help you when it comes to display an animated gif anymore than any of the many download/cache tools out there.Apelles
E
7

Try this, bellow code display gif file in progressbar

loading_activity.xml(in Layout folder)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" >

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/custom_loading"
        android:visibility="gone" />

</RelativeLayout>

custom_loading.xml(in drawable folder)

here i put black_gif.gif(in drawable folder), you can put your own gif here

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/black_gif"
    android:pivotX="50%"
    android:pivotY="50%" />

LoadingActivity.java(in res folder)

public class LoadingActivity extends Activity {

    ProgressBar bar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading);
        bar = (ProgressBar) findViewById(R.id.progressBar);
        bar.setVisibility(View.VISIBLE);

    }

}
Edaedacious answered 15/5, 2014 at 6:3 Comment(2)
I see you rotate the gif. Why?Dellinger
How can you put gif in drawable folder?Munro
S
7

Nobody has mentioned the Ion or Glide library. they work very well.

It's easier to handle compared to a WebView.

Stagger answered 2/12, 2014 at 14:54 Comment(0)
H
5

I have had success with the solution proposed within this article, a class called GifMovieView, which renders a View which can then be displayed or added to a specific ViewGroup. Check out the other methods presented in parts 2 and 3 of the specified article.

The only drawback to this method is that the antialiasing on the movie is not that good (must be a side-effect of using the "shady" Android Movie Class). You are then better off setting the background to a solid color within your animated GIF.

Humidor answered 15/8, 2012 at 8:47 Comment(0)
R
4

Some thoughts on the BitmapDecode example... Basically it uses the ancient, but rather featureless Movie class from android.graphics. On recent API versions you need to turn off hardware acceleration, as described here. It was segfaulting for me otherwise.

<activity
            android:hardwareAccelerated="false"
            android:name="foo.GifActivity"
            android:label="The state of computer animation 2014">
</activity>

Here is the BitmapDecode example shortened with only the GIF part. You have to make your own Widget (View) and draw it by yourself. Not quite as powerful as an ImageView.

import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.*;
import android.view.View;

public class GifActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GifView(this));
    }

    static class GifView extends View {
        Movie movie;

        GifView(Context context) {
            super(context);
            movie = Movie.decodeStream(
                    context.getResources().openRawResource(
                            R.drawable.some_gif));
        }
        @Override
        protected void onDraw(Canvas canvas) {   
            if (movie != null) {
                movie.setTime(
                    (int) SystemClock.uptimeMillis() % movie.duration());
                movie.draw(canvas, 0, 0);
                invalidate();
            }
        }
    }
}

2 other methods, one with ImageView another with WebView can be found in this fine tutorial. The ImageView method uses the Apache licensed android-gifview from Google Code.

Rambow answered 1/3, 2014 at 3:15 Comment(1)
@luboz can you please tell me which method is good for android performance... i want to use animated gif for splash screen loading bar. so can you please suggest which method is better. also i want to know that by using image view method is it possible to use scale type property ?Cinder
D
4

@PointerNull gave good solution, but it is not perfect. It doesn't work on some devices with big files and show buggy Gif animation with delta frames on pre ICS version. I found solution without this bugs. It is library with native decoding to drawable: koral's android-gif-drawable.

Decompress answered 3/4, 2014 at 6:58 Comment(0)
R
3

For only android API (Android Pie)28 and +

use AnimatedImageDrawable as
// ImageView from layout
val ima : ImageView = findViewById(R.id.img_gif)
// create AnimatedDrawable 
val decodedAnimation = ImageDecoder.decodeDrawable(
        // create ImageDecoder.Source object
        ImageDecoder.createSource(resources, R.drawable.tenor))
// set the drawble as image source of ImageView
ima.setImageDrawable(decodedAnimation)
// play the animation
(decodedAnimation as? AnimatedImageDrawable)?.start()

XML code, add a ImageView

<ImageView
    android:id="@+id/img_gif"
    android:background="@drawable/ic_launcher_background" <!--Default background-->
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_width="200dp"
    android:layout_height="200dp" />

AnimatedImageDrawable is a child of Drawable and created by ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawable which further required the instance of ImageDecoder.Source created by ImageDecoder.createSource.

ImageDecoder.createSource can only take source as a name, ByteBuffer, File, resourceId, URI, ContentResolver to create source object and uses it to create AnimatedImageDrawable as Drawable (polymorphic call)

static ImageDecoder.Source  createSource(AssetManager assets, String fileName)
static ImageDecoder.Source  createSource(ByteBuffer buffer)
static ImageDecoder.Source  createSource(File file)
static ImageDecoder.Source  createSource(Resources res, int resId)
static ImageDecoder.Source  createSource(ContentResolver cr, Uri uri)

Note: You can also create Bitmap using ImageDecoder#decodeBitmap.

Output:

AnimatedDrawable also supports resizing, frame and color manipulation

Recollected answered 8/8, 2018 at 2:26 Comment(0)
D
2

Put it into a WebView, it has to be able to display it correctly, since the default browser supports gif files. (Froyo+, if i am not mistaken)

Dorsy answered 23/8, 2013 at 7:21 Comment(2)
This is not true. Not all browsers support GIF.Marcello
Hopefully we don't need all browsers... Stock browser supports it since android 2.2, so don't downvote me, please. A WebView will definitely display the GIF!Dorsy
E
2

There are two options to load animated gifs into our Android apps

1)Using Glide to load the gif into an ImageView.

    String urlGif = "https://cdn.dribbble.com/users/263558/screenshots/1337078/dvsd.gif";
    //add Glide implementation into the build.gradle file.
    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    Uri uri = Uri.parse(urlGif);
    Glide.with(getApplicationContext()).load(uri).into(imageView);

2) Using an html to load the gif into a WebView

Create the html with the address to the .gif file:

<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>

store this file into the assets directory:

enter image description here

The load this html into the WebView of your application:

    WebView webView =  (WebView)findViewById(R.id.webView);
    webView = (WebView) findViewById(R.id.webView);
    webView.loadUrl("file:///android_asset/html/webpage_gif.html");

Heres is a complete example of this two options.

enter image description here

Extravagance answered 19/1, 2018 at 17:3 Comment(0)
A
1

I think the better library to handle gif files is this one: by koral

Used it and i'm successful and this library is dedicated to GIF'S; but where as the picasso and glide are general purpose image framework; so i think the developers of this library have entirely concentrated on gif files

Aesthetic answered 29/3, 2016 at 13:44 Comment(0)
P
1

Use fresco. Here's how to do it:

http://frescolib.org/docs/animations.html

Here's the repo with the sample:

https://github.com/facebook/fresco/tree/master/samples/animation

Beware fresco does not support wrap content!

Poorhouse answered 8/6, 2016 at 11:5 Comment(0)
A
1

Just wanted to add that the Movie class is now deprecated.

This class was deprecated in API level P.

It is recommended to use this

AnimatedImageDrawable

Drawable for drawing animated images (like GIF).

Animus answered 23/5, 2018 at 5:23 Comment(0)
B
0

Similar to what @Leonti said, but with a little more depth:

What I did to solve the same problem was open up GIMP, hide all layers except for one, export it as its own image, and then hide that layer and unhide the next one, etc., until I had individual resource files for each one. Then I could use them as frames in the AnimationDrawable XML file.

Brunk answered 9/12, 2010 at 21:36 Comment(1)
You could use gifsicle to extract the frames if you don't have that much time. Also python or bash are very handy when generating xml files.Rambow
C
0

Something I did for showing gifs in apps. I extended ImageView so people can use its attributes freely. It can show gifs from url or from the assets directory. The library also makes it easy for extending classes to inherit from it and extend it to support different methods to initialize the gif.

https://github.com/Gavras/GIFView

There's a little guide on the github page.

It was also published on Android Arsenal:

https://android-arsenal.com/details/1/4947

Use example:

From XML:

<com.whygraphics.gifview.gif.GIFView xmlns:gif_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_activity_gif_vie"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="center"
        gif_view:gif_src="url:http://pop.h-cdn.co/assets/16/33/480x264/gallery-1471381857-gif-season-2.gif" />

In the activity:

    GIFView mGifView = (GIFView) findViewById(R.id.main_activity_gif_vie);

    mGifView.setOnSettingGifListener(new GIFView.OnSettingGifListener() {
                @Override
                public void onSuccess(GIFView view, Exception e) {
                    Toast.makeText(MainActivity.this, "onSuccess()", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(GIFView view, Exception e) {

        }
});

Setting the gif programmatically:

mGifView.setGifResource("asset:gif1");
Camfort answered 26/12, 2016 at 10:58 Comment(0)
W
0

Easiest way - Can be consider the below code

We can take advantage of Imageview setImageResource , refer below code for the same.

The below code can be used to show the image like gif incase if you have the multiple split image of gif. Just split the gif into individual png from a online tool and put image in the drawable like the below order

image_1.png, image_2.png, etc.

Have the handler to change the image dynamically.

int imagePosition = 1;
    Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            public void run() {
                updateImage();
            }
        };




    public void updateImage() {

                appInstance.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        int resId = getResources().getIdentifier("image_" + imagePosition, "drawable", appInstance.getPackageName());
                        gifImageViewDummy.setImageResource(resId);
                        imagePosition++;
    //Consider you have 30 image for the anim
                        if (imagePosition == 30) {
//this make animation play only once
                            handler.removeCallbacks(runnable);

                        } else {
    //You can define your own time based on the animation
                            handler.postDelayed(runnable, 50);
                        }

//to make animation to continue use below code and remove above if else
// if (imagePosition == 30)
//imagePosition = 1;
// handler.postDelayed(runnable, 50);
// 
                    }
                });
              }
Withal answered 1/2, 2018 at 7:27 Comment(0)
A
0

The easy way to display animated GIF directly from URL to your app layout is to use WebView class.

Step 1: In your layout XML

<WebView
android:id="@+id/webView"
android:layout_width="50dp"
android:layout_height="50dp"
/>

Step 2: In your Activity

WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);

Step 3: In your Manifest.XML make Internet permission

<uses-permission android:name="android.permission.INTERNET" />

Step 4: In case you want to make your GIF background transparent and make GIF fit to your Layout

wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);
Absolutely answered 26/2, 2018 at 10:28 Comment(1)
Thanks for the workaround but considerable developer might not want to have non-native render due some implications as a memory impact, CPU usage and battery lifetimeWoolly
K
0

If you want to use Glide for loading gif:

Glide.with(this)
        .asGif()
        .load(R.raw.onboarding_layers) //Your gif resource
        .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
        .listener(new RequestListener<GifDrawable>() {
            @Override
            public boolean onLoadFailed(@Nullable @org.jetbrains.annotations.Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
                resource.setLoopCount(1);
                return false;
            }
        })
        .into((ImageView) view.findViewById(R.id.layer_icons));
Karlsbad answered 26/7, 2021 at 20:16 Comment(0)
L
0

To save resources there is glide library for. Have no idea why to use anything else, especialy webview to show image only. Glide is perfect and easy library that prepares animated drawable from gif and put it directly to imageview. The logic of gifdrawable handle animation itself. Gif have lzw ziped raw rgb data of an animation inside. There is no reason for complicated usage of webview and manage more files to show just a gif file in app.

Lupercalia answered 27/7, 2021 at 4:15 Comment(0)
D
-3

First of all the Android browser should support Animated GIFs. If it doesn't then it's a bug! Have a look at the issue trackers.

If you're displaying these animated GIFs outside of a browser it might be a different story. To do what you're asking would require external library that supports the decoding of Animated GIFs.

The first port of call would be to look at Java2D or JAI (Java Advanced Imaging) API, although I would be very surprised if Android Dalvik would support those libraries in your App.

Dicast answered 30/9, 2010 at 15:11 Comment(1)
some devices don't show animated gifs, even on a web browser. as an example, i know that galaxy mini with android 2.3.6 doesn't show them.Opponent
C
-8
public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private Bitmap mBitmap;
    private Bitmap mBitmap2;
    private Bitmap mBitmap3;
    private Bitmap mBitmap4;
    private Drawable mDrawable;

    private Movie mMovie;
    private long mMovieStart;

    // Set to false to use decodeByteArray
    private static final boolean DECODE_STREAM = true;

    private static byte[] streamToBytes(InputStream is) {
      ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
      byte[] buffer = new byte[1024];
      int len;
      try {
        while ((len = is.read(buffer)) >= 0) {
          os.write(buffer, 0, len);
        }
      } catch (java.io.IOException e) {
      }
      return os.toByteArray();
    }

    public SampleView(Context context) {
      super(context);
      setFocusable(true);

      java.io.InputStream is;
      is = context.getResources().openRawResource(R.drawable.icon);

      BitmapFactory.Options opts = new BitmapFactory.Options();
      Bitmap bm;

      opts.inJustDecodeBounds = true;
      bm = BitmapFactory.decodeStream(is, null, opts);

      // now opts.outWidth and opts.outHeight are the dimension of the
      // bitmap, even though bm is null

      opts.inJustDecodeBounds = false; // this will request the bm
      opts.inSampleSize = 4; // scaled down by 4
      bm = BitmapFactory.decodeStream(is, null, opts);

      mBitmap = bm;

      // decode an image with transparency
      is = context.getResources().openRawResource(R.drawable.icon);
      mBitmap2 = BitmapFactory.decodeStream(is);

      // create a deep copy of it using getPixels() into different configs
      int w = mBitmap2.getWidth();
      int h = mBitmap2.getHeight();
      int[] pixels = new int[w * h];
      mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
      mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_8888);
      mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_4444);

      mDrawable = context.getResources().getDrawable(R.drawable.icon);
      mDrawable.setBounds(150, 20, 300, 100);

      is = context.getResources().openRawResource(R.drawable.animated_gif);

      if (DECODE_STREAM) {
        mMovie = Movie.decodeStream(is);
      } else {
        byte[] array = streamToBytes(is);
        mMovie = Movie.decodeByteArray(array, 0, array.length);
      }
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(0xFFCCCCCC);

      Paint p = new Paint();
      p.setAntiAlias(true);

      canvas.drawBitmap(mBitmap, 10, 10, null);
      canvas.drawBitmap(mBitmap2, 10, 170, null);
      canvas.drawBitmap(mBitmap3, 110, 170, null);
      canvas.drawBitmap(mBitmap4, 210, 170, null);

      mDrawable.draw(canvas);

      long now = android.os.SystemClock.uptimeMillis();
      if (mMovieStart == 0) { // first time
        mMovieStart = now;
      }
      if (mMovie != null) {
        int dur = mMovie.duration();
        if (dur == 0) {
          dur = 1000;
        }
        int relTime = (int) ((now - mMovieStart) % dur);
        mMovie.setTime(relTime);
        mMovie.draw(canvas, getWidth() - mMovie.width(), getHeight()
            - mMovie.height());
        invalidate();
      }
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

  public PictureLayout(Context context) {
    super(context);
  }

  public PictureLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
Crenshaw answered 30/7, 2012 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.