Подтвердить что ты не робот

Как показать анимированное изображение GIF в приложении Android?

Я хочу показать анимированный GIF-образ в приложении для Android, как показано ниже. Я пробовал веб-просмотр, но не имел успеха. Как показать анимированный gif в приложении? enter image description here

4b9b3361

Ответ 1

После долгого поиска Google я знал, что для GIF-изображений нет встроенной поддержки. Не существует правильных решений для отображения анимированного gif в приложении. Вы можете просмотреть Это решение

чтобы анимационная игра GIF в макете.

Ответ 2

Вы также можете использовать этот lib, чтобы легко поддерживать gifDrawable.

Просто используйте GifImageView вместо обычного ImageView:

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

и найдите ваш gif файл под src attr. Это все!

Ответ 3

Вы можете использовать Glide:

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

Ответ 4

Лучшее и простое решение для отображения изображения GIF на Android и он будет работать отлично:

  • Открыть build.gradle(модуль: приложение)
  • установить зависимости: compile 'pl.droidsonroids.gif: android-gif-drawable: 1.1. +'
  • Откройте папку макета и поместите этот код, где вы хотите отобразить изображение GIF: 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", замените 'your_gif_file_name' на ваш желаемый файл изображения gif

Ответ 5

Я также пытался сделать то же самое, но Android не показывает gif-изображения с анимацией. Если вы хотите достичь того же, вы получите несколько кадров вашего анимированного изображения, а затем используйте анимацию с кадром по кадру.

У вас может быть ссылка в приведенной ниже ссылке. http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Ответ 6

Вам не нужна библиотека, просто используйте этот код:

Шаг 1: Создайте файл с именем 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;
}
}

Шаг 2: Добавьте следующие строки в res/attrs.xml

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

Шаг 3: Добавьте эту строку в ваш AndroidManifest.xml в определенной деятельности.

android:hardwareAccelerated="false"

Шаг 4: Создайте это представление в XML:

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

Шаг 5 В родительской активности, в которой вы создали представление, добавьте следующие строки:

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

Ответ 7

Попробуйте следующим образом:

    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

Ответ 8

Возможно, у вас есть возможность попробовать этот lib GifImageView. Он очень прост и удобен в использовании. Следующий пример кода из README этого проекта.

@Override protected void onCreate (окончательный 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(); }

Ответ 9

обновление:

Существует обновленная версия андроидного арсенала и на странице GitHub GIFView.

Это что-то маленькое, что я сделал, когда кто-то попросил меня помочь ему показать gifs. Большинство вещей, которые я нашел в Интернете, были сторонними библиотеками и решениями, которые использовали поток пользовательского интерфейса для обработки gif, который не так хорошо работал на моем телефоне, поэтому я решил сделать это сам с помощью Android Movie API. Я намеренно расширил ImageView, чтобы мы могли использовать такие атрибуты, как scaleType. Это поддерживает получение gif из url или из каталога ресурсов. Я документировал все.

Как его использовать:

Простой пример использования в файле макета xml:

<[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" />

Код:

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 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 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 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/значения/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>

Ответ 10

Вы можете просто добавить веб-просмотр и показать в нем изображение gif, 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");

Это покажет изображение gif в вашем приложении.

Надеюсь, это поможет! Удачи!