Home » Android » user interface – How to show Animated GIF image in android application?

user interface – How to show Animated GIF image in android application?

Posted by: admin April 23, 2020 Leave a comment

Questions:

I want to show an animated GIF image in an android application like the image below. I have tried the webview but no success. How to show the animated gif in the application?enter image description here

How to&Answers:

You can also use this lib to easily support a gifDrawable.

Just use GifImageView instead of normal ImageView:

<pl.droidsonroids.gif.GifImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/your_anim"/>

and locate your gif-file under the src attr. That’s all!

Answer:

You can use Glide :

ImageView imageView = (ImageView) findViewById(R.id.imageView);
GlideDrawableImageViewTarget imageViewTarget = new GlideDrawableImageViewTarget(imageView);
Glide.with(this).load(R.raw.sample_gif).into(imageViewTarget);

Answer:

After long Google search, I knew that there is no native support for the GIF images. There are no proper solutions for showing the animated gif in application. You can view This solution

to make the animated gif play in a layout.

Answer:

Best and easiest solution to display GIF image in Android
and it will work perfectly:

  • Open build.gradle (Module: app)
  • put in dependencies:
    compile ‘pl.droidsonroids.gif:android-gif-drawable:1.1.+’
  • Open layout folder and put this code where you want to display GIF image:
    e-g activity_main.xml

     <pl.droidsonroids.gif.GifImageView
          android:layout_width="150dp"
          android:layout_height="wrap_content"
          android:src="@drawable/your_gif_file_name"/>
    
  • android:src=”@drawable/your_gif_file_name”, Replace ‘your_gif_file_name’ with your desired gif image file

Answer:

You don’t need any library, simply use this code:

Step 1:
Create a file named GIFView.java

package com.thigale.testproject;

/**
 * Created by Thigale Sameer on 11-12-16.
 */

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.view.View;

import java.io.InputStream;

public class GifView extends View {
public Movie mMovie;
public long movieStart;
private int gifId;

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

public GifView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initializeView(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res-auto", "src", 0));
}

public GifView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initializeView(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res-auto", "src", 0));
}

private void initializeView(final int id) {
    InputStream is = getContext().getResources().openRawResource(id);
    mMovie = Movie.decodeStream(is);
    this.gifId = id;
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.TRANSPARENT);
    super.onDraw(canvas);
    long now = android.os.SystemClock.uptimeMillis();

    if (movieStart == 0) {
        movieStart = now;
    }

    if (mMovie != null) {
        int relTime = (int) ((now - movieStart) % mMovie.duration());
        mMovie.setTime(relTime);
        mMovie.draw(canvas, getWidth() - mMovie.width(), getHeight() - mMovie.height());
        this.invalidate();
    }
}

public void setGIFResource(int resId) {
    this.gifId = resId;
    initializeView(this.gifId);
}

public int getGIFResource() {
    return this.gifId;
}
}

Step 2:
Add following lines in res/attrs.xml

<declare-styleable name="GIFView">
  <attr name="src" format="reference" />
</declare-styleable>

Step 3:
Add this line your AndroidManifest.xml in specific activity

android:hardwareAccelerated="false"

Step 4:
Create this view in your XML:

<com.thigale.testproject.GifView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    components:src="@drawable/loading" />

Step 5
In the parent activity where you created the view, add the following lines:

xmlns:components="http://schemas.android.com/apk/res-auto"

Answer:

I tried so many library to use Animated gif .
But every library is lagging and crushing .
But now , after one or two day research i got a idea to use animated gif and the performance is very good no lagging no crushing.

Solution is that use Glide

Follow the below step .

in xml file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#62b849"
    tools:context=".MainActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:id="@+id/splace_image_view"
        android:layout_centerInParent="true"/>

</RelativeLayout> 

and in your java file

 ImageView imageView = findViewById(R.id.splace_image_view);

Glide
        .with(this)
        .load(R.drawable.football)
        .into(imageView);

Answer:

I have also tried to do the same but Android doesn’t show gif images with Animation. If you want to achieve the same then you have take few frames of your animated Image and then use frame by frame animation.

You Can have reference in the below link.
http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Answer:

Try this way :

    Movie movie,movie1;
    InputStream is=null,is1=null;
    long moviestart;
    long moviestart1;
    public GIFView(Context context) {
        super(context);
        is=context.getResources().openRawResource(R.drawable.hxps);
        is1=context.getResources().openRawResource(R.drawable.cartoon);
        movie=Movie.decodeStream(is);
        movie1=Movie.decodeStream(is1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFCCCCCC);
        super.onDraw(canvas);
        long now=android.os.SystemClock.uptimeMillis();
        System.out.println("now="+now);
         if (moviestart == 0) {   // first time
             moviestart = now;

         }
         if(moviestart1==0)
         {
             moviestart1=now;
         }
         System.out.println("\tmoviestart="+moviestart);
         int relTime = (int)((now - moviestart) % movie.duration()) ;
         int relTime1=(int)((now - moviestart1)% movie1.duration());
         System.out.println("time="+relTime+"\treltime="+movie.duration());
         movie.setTime(relTime);
         movie1.setTime(relTime1);
         movie.draw(canvas,0,0);
         movie1.draw(canvas,10,300);
         this.invalidate();
    }

enter image description here

Answer:

You may have a try on this lib GifImageView. It’s very simple and easy to use. The following sample code is from README of this project.

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

gifView = new GifImageView(context);
gifView.setBytes(bitmapData);
setContentView(gifView);

}

@Override
protected void onStart() {
super.onStart();
gifView.startAnimation();
}

@Override
protected void onStop() {
super.onStop();
gifView.stopAnimation();
}

Answer:

You could just add a webview and show a gif image in that, Like:

webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(new WebViewClient());
    webView.loadUrl("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Rotating_earth_(large).gif/200px-Rotating_earth_(large).gif");

This will show the gif image in your app.

Hope it helps! Good Luck!

Answer:

update:

There is an up-to-date version on android arsenal and in the GitHub page of GIFView.

This is something small I did when someone asked me to help him with showing gifs.
Most of the things I found online were third-party libraries and solutions which used the UI Thread for processing the gif which didn’t go so well on my phone so I decided to do it myself with the help of android’s Movie API.
I deliberately made it extend ImageView so we can use attributes like scaleType.
This supports retrieving gif from url or from the assets directory. I documented everything.

How to use it:

Simple example of using it in a xml layout file:

<[package].GIFView xmlns:gif_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/gif_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        gif_view:gif_src="asset:gif1" />

The code:

GIF.java:

/**
 * Class that represents a gif instance.
 */
public class GIF {

    private static final Bitmap.Config DEF_VAL_CONFIG = Bitmap.Config.RGB_565;

    private static final int DEF_VAL_DELAY_IN_MILLIS = 33;

    // the gif's frames are stored in a movie instance
    private Movie movie;

    // the canvas of this gif
    private Canvas canvas;

    // the bitmap of this gif
    private Bitmap bitmap;

    // the start time of the gif
    private long gifStartTime;

    // the executor of the gif's thread
    private ScheduledExecutorService executor;

    // the main runnable of the gif
    private Runnable mainRunnable;

    // delay in millis between frames
    private int delayInMillis;

    private OnFrameReadyListener onFrameReadyListener;

    private Handler listenerHandler;

    private Runnable listenerRunnable;

    /**
     * Creates Gif instance based on the passed InputStream.
     *
     * @param in the InputStream
     * @throws InputStreamIsNull                        if in is null
     * @throws InputStreamIsEmptyOrUnavailableException if in is empty or unavailable
     */
    public GIF(InputStream in) {
        this(in, DEF_VAL_CONFIG);
    }

    /**
     * Creates Gif instance based on the passed InputStream and the config.
     *
     * @param in     the InputStream
     * @param config the Config
     * @throws NullPointerException                     if config is null
     * @throws InputStreamIsNull                        if in is null
     * @throws InputStreamIsEmptyOrUnavailableException if in is empty or unavailable
     */
    public GIF(InputStream in, Bitmap.Config config) {
        if (in == null)
            throw new InputStreamIsNull("the input stream is null");

        this.movie = Movie.decodeStream(in);

        if (movie == null)
            throw new InputStreamIsEmptyOrUnavailableException("the input steam is empty or unavailable");

        this.bitmap = Bitmap.createBitmap(movie.width(), movie.height(), config);

        // associates the canvas with the bitmap
        this.canvas = new Canvas(bitmap);

        this.mainRunnable = new Runnable() {
            @Override
            public void run() {
                draw();
                invokeListener();
            }
        };

        setDelayInMillis(DEF_VAL_DELAY_IN_MILLIS);
    }

    /**
     * Register a callback to be invoked when the gif changed a frame.
     * Invokes methods from a special thread.
     *
     * @param onFrameReadyListener the listener to attach
     */
    public void setOnFrameReadyListener(OnFrameReadyListener onFrameReadyListener) {
        setOnFrameReadyListener(onFrameReadyListener, null);
    }

    /**
     * Register a callback to be invoked when the gif changed a frame.
     * Invokes methods from the specified handler.
     *
     * @param onFrameReadyListener the listener to attach
     * @param handler              the handler
     */
    public void setOnFrameReadyListener(OnFrameReadyListener onFrameReadyListener, Handler handler) {
        this.onFrameReadyListener = onFrameReadyListener;
        listenerHandler = handler;

        if (listenerHandler != null)
            listenerRunnable = new Runnable() {
                @Override
                public void run() {
                    GIF.this.onFrameReadyListener.onFrameReady(bitmap);
                }
            };

        else
            listenerRunnable = null;
    }

    /**
     * Sets the delay in millis between every calculation of the next frame to be set.
     *
     * @param delayInMillis the delay in millis
     * @throws IllegalArgumentException if delayInMillis is non-positive
     */
    public void setDelayInMillis(int delayInMillis) {
        if (delayInMillis <= 0)
            throw new IllegalArgumentException("delayInMillis must be positive");

        this.delayInMillis = delayInMillis;
    }

    /**
     * Starts the gif.
     * If the gif is already running does nothing.
     */
    public void startGif() {
        if (executor != null)
            return;

        executor = Executors.newSingleThreadScheduledExecutor();

        final int INITIAL_DELAY = 0;
        executor.scheduleWithFixedDelay(mainRunnable, INITIAL_DELAY,
                delayInMillis, TimeUnit.MILLISECONDS);
    }

    /**
     * Stops the gif.
     * If the gif is not running does nothing.
     */
    public void stopGif() {
        if (executor == null)
            return;

        executor.shutdown();

        // waits until the thread is finished
        while (true) {
            try {
                executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
                break;
            } catch (InterruptedException ignored) {
            }
        }

        executor = null;
    }

    // calculates the frame and draws it to the bitmap through the canvas
    private void draw() {
        // if gifStartTime == 0 inits it for the first time
        if (gifStartTime == 0)
            gifStartTime = SystemClock.uptimeMillis();

        long timeElapsed = SystemClock.uptimeMillis() - gifStartTime;

        int timeInGif = (int) (timeElapsed % movie.duration());
        movie.setTime(timeInGif);

        movie.draw(canvas, 0, 0);
    }

    // invokes the listener
    private void invokeListener() {
        if (onFrameReadyListener == null)
            return;

        // if handler was given invokes from it, otherwise invokes from this thread
        if (listenerHandler != null)
            listenerHandler.post(listenerRunnable);
        else
            onFrameReadyListener.onFrameReady(bitmap);
    }

    /**
     * Interface definition for a callback to be invoked when the gif changed a frame.
     */
    public interface OnFrameReadyListener {
        /**
         * Called when the gif changed a frame.
         * <p>
         * Note: If a handler was given with the listener this method
         * invokes from the handler, otherwise this method
         * invokes from a special thread.
         * <p>
         * Note: This bitmap is mutable and used by the gif instance
         * thus it is not recommended to mutate it.
         *
         * @param bitmap the new bitmap of the gif
         */
        void onFrameReady(Bitmap bitmap);
    }

    /**
     * Definition of a runtime exception class to throw when the inputStream is null.
     */
    public static class InputStreamIsNull extends NullPointerException {

        /**
         * Creates a new instance.
         */
        public InputStreamIsNull() {
            super();
        }

        /**
         * * Creates a new instance with a message.
         *
         * @param message the message
         */
        public InputStreamIsNull(String message) {
            super(message);
        }
    }

    /**
     * Definition of a runtime exception class to throw when the inputStream is empty or unavailable.
     */
    public static class InputStreamIsEmptyOrUnavailableException extends RuntimeException {

        /**
         * Creates a new instance.
         */
        public InputStreamIsEmptyOrUnavailableException() {
            super();
        }

        /**
         * * Creates a new instance with a message.
         *
         * @param message the message
         */
        public InputStreamIsEmptyOrUnavailableException(String message) {
            super(message);
        }
    }
}

GIFView.java:

/** * A view that can show gifs. * <p> * XML Attributes: * <p> * gif_src: * A string that represents the gif's source. * <p> * - If you want to get the gif from a url * concatenate the string "url:" with the full url. * <p> * - if you want to get the gif from the assets directory * concatenate the string "asset:" with the full path of the gif * within the assets directory. You can exclude the .gif extension. * <p> * for example if you have a gif in the path "assets/ex_dir/ex_gif.gif" * the string should be: "asset:ex_dir/ex_gif" * <p> * delay_in_millis: * A positive integer that represents how many milliseconds * should pass between every calculation of the next frame to be set. */ public class GIFView extends ImageView { public static final String RESOURCE_PREFIX_URL = "url:"; public static final String RESOURCE_PREFIX_ASSET = "asset:"; private static final int DEF_VAL_DELAY_IN_MILLIS = 33; // the gif instance private GIF gif; // keeps track if the view is in the middle of setting the gif private boolean settingGif; private GIF.OnFrameReadyListener gifOnFrameReadyListener; private OnSettingGifListener onSettingGifListener; // delay in millis between frames private int delayInMillis; /** * Creates a new instance in the passed context. * * @param context the context */ public GIFView(Context context) { super(context); init(null); } /** * Creates a new instance in the passed context with the specified set of attributes. * * @param context the context * @param attrs the attributes */ public GIFView(Context context, AttributeSet attrs) { super(context, attrs); init(attrs); } // inits the view private void init(AttributeSet attrs) { this.gifOnFrameReadyListener = new GIF.OnFrameReadyListener() { @Override public void onFrameReady(Bitmap bitmap) { setImageBitmap(bitmap); } }; setDelayInMillis(DEF_VAL_DELAY_IN_MILLIS); if (attrs != null) initAttrs(attrs); } // inits the view with the specified attributes private void initAttrs(AttributeSet attrs) { TypedArray typedArray = getContext().getTheme().obtainStyledAttributes( attrs, R.styleable.gif_view, 0, 0); try { // gets and sets the delay in millis. int delayInMillis = typedArray.getInt(R.styleable.gif_view_delay_in_millis, DEF_VAL_DELAY_IN_MILLIS); if (delayInMillis != DEF_VAL_DELAY_IN_MILLIS) setDelayInMillis(delayInMillis); // gets the source of the gif and sets it String string = typedArray.getString(R.styleable.gif_view_gif_src); if (string != null) setGifResource(typedArray.getString(R.styleable.gif_view_gif_src)); } finally { typedArray.recycle(); } } /** * Register callbacks to be invoked when the view finished setting a gif. * * @param onSettingGifListener the listener to attach */ public void setOnSettingGifListener(OnSettingGifListener onSettingGifListener) { this.onSettingGifListener = onSettingGifListener; } /** * Sets the delay in millis between every calculation of the next frame to be set. * * @param delayInMillis the delay in millis * @throws IllegalArgumentException if delayInMillis is non-positive */ public void setDelayInMillis(int delayInMillis) { if (delayInMillis <= 0) throw new IllegalArgumentException("delayInMillis must be positive"); this.delayInMillis = delayInMillis; if (gif != null) gif.setDelayInMillis(delayInMillis); } /** * Returns true if the view is in the process of setting the gif, false otherwise. * * @return true if the view is in the process of setting the gif, false otherwise */ public boolean isSettingGif() { return settingGif; } /** * Sets the gif of this view and starts it. * <p> * Note that every exception while setting the gif is only sent to the * OnSettingGifListener instance attached to this view. * <p> * If the view has already begun setting another gif, does nothing. * You can query this state with isSettingGif(). * <p> * The string passed must be in the following format: * <p> * - If you want to get the gif from a url * concatenate the string "url:" with the full url. * <p> * - if you want to get the gif from the assets directory * concatenate the string "asset:" with the full path of the gif * within the assets directory. You can exclude the .gif extension. * <p> * You can use the Constants: * <p> * GIFView.RESOURCE_PREFIX_URL = "url:" * GIFView.RESOURCE_PREFIX_ASSET = "asset:" * <p> * for example if you have a gif in the path "assets/ex_dir/ex_gif.gif" * invoke the method like this: setGifResource(GIFView.RESOURCE_PREFIX_ASSET + "ex_dir/ex_gif"); * * @param string the string * @throws IllegalArgumentException if the string format is invalid */ public void setGifResource(String string) { if (settingGif) return; // stops the gif if it is running if (gif != null) gif.stopGif(); // defines some finals for readability final int URL_START_INDEX = RESOURCE_PREFIX_URL.length(); final int ASSET_START_INDEX = RESOURCE_PREFIX_ASSET.length(); final String GIF_EXTENSION = ".gif"; if (string.startsWith(RESOURCE_PREFIX_URL)) { // notifies setting gif has started settingGif = true; // gets the url String url = string.substring(URL_START_INDEX); new AsyncSettingOfGif() { @Override protected InputStream getGifInputStream(String url) throws Exception { // gets the input stream from the url return (InputStream) new URL(url).getContent(); } }.execute(url); } else if (string.startsWith(RESOURCE_PREFIX_ASSET)) { // notifies setting gif has started settingGif = true; // gets the asset path String assetPath = string.substring(ASSET_START_INDEX) .replaceAll("[\\\\/]", File.separator); // replacing file separators if (!assetPath.endsWith(GIF_EXTENSION)) assetPath += GIF_EXTENSION; new AsyncSettingOfGif() { @Override protected InputStream getGifInputStream(String assetPath) throws Exception { // gets the input stream from the assets directory return GIFView.this.getResources().getAssets().open(assetPath); } }.execute(assetPath); // if string format is invalid } else { throw new IllegalArgumentException("string format is invalid"); } } /** * Called when the view finished to set the gif * or an exception has occurred. * If there are no exceptions e is null. * <p> * Note that the gif can be initialized properly * and one or more exceptions can be caught in the way. * * @param e the Exception */ protected void onFinishSettingGif(Exception e) { // notifies setting the gif has finished settingGif = false; if (gif != null) onSuccess(); else onFailure(e); } // on finish setting the gif private void onSuccess() { gif.setOnFrameReadyListener(gifOnFrameReadyListener, getHandler()); gif.setDelayInMillis(delayInMillis); startGif(); if (onSettingGifListener != null) onSettingGifListener.onSuccess(this); } // when an exception has occurred while trying to set the gif private void onFailure(Exception e) { if (onSettingGifListener != null) onSettingGifListener.onFailure(this, e); } /** * Starts the gif. * If the gif is already running does nothing. * * @throws IllegalStateException if the gif has not been initialized yet */ public void startGif() { if (gif == null || settingGif) throw new IllegalStateException("the gif has not been initialized yet"); gif.startGif(); } /** * Stops the gif. * If the gif is not running does nothing. * * @throws IllegalStateException if the gif has not been initialized yet */ public void stopGif() { if (gif == null || settingGif) throw new IllegalStateException("the gif has not been initialized yet"); gif.stopGif(); } /** * Interface definition for callbacks to be invoked when setting a gif. */ public interface OnSettingGifListener { /** * Called when a gif has successfully set. * * @param view the GIFView */ void onSuccess(GIFView view); /** * Called when a gif cannot be set. * * @param view the GIFView * @param e the Exception */ void onFailure(GIFView view, Exception e); } /** * Definition of an Exception class to throw when the view cannot initialize the gif. */ public static class CannotInitGifException extends Exception { /** * Creates a new instance. */ public CannotInitGifException() { super(); } /** * * Creates a new instance with a message. * * @param message the message */ public CannotInitGifException(String message) { super(message); } } /** * A sub-class of AsyncTask to easily perform an async task of setting a gif. * <p> * The default implementation of AsyncSettingOfGif.doInBackground() is to try and init the gif * from the input stream returned from AsyncSettingOfGif.getGifInputStream() and notify * GIFView.onFinishSettingGif() sending to it the exception, if occurred, or null. * <p> * Implementations of this class should override AsyncSettingOfGif.getGifInputStream() * to return the right input stream for the gif based on the string argument. * The string argument can be, for example, a url to retrieve the input stream from. */ protected abstract class AsyncSettingOfGif extends AsyncTask<String, Void, Exception> { @Override protected Exception doInBackground(String... string) { CannotInitGifException exceptionToSend = null; try (InputStream in = getGifInputStream(string[0])) { // tries to init the gif gif = new GIF(in); } catch (Exception e) { // prepares the message of the exception String message = e.getMessage(); if (e instanceof FileNotFoundException) message = "file not found: " + message; // prepares the exception to send back exceptionToSend = new CannotInitGifException(message); } return exceptionToSend; } /** * Override this method to return the right input stream for the gif based on the string argument. * The string argument can be, for example, a url to retrieve the input stream from. * * @param string the string * @return an InputStream of a gif * @throws Exception if an exception has occurred */ protected abstract InputStream getGifInputStream(String string) throws Exception; @Override protected void onPostExecute(Exception e) { onFinishSettingGif(e); } } } 

res/values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="gif_view"> <attr name="gif_src" format="string" /> <attr name="delay_in_millis" format="integer" /> </declare-styleable> </resources>