Set GIF image to Custom ImageView

2019-07-29 16:52发布

问题:

I have custom ImageView for animated GIF image. i want to show GIF image, I tried but in this case it is contain url in Async instead I want to show GIF image from raw folder without using Glide. Anyone have any idea how to show image? Please guyz help to solve this problem!!!

I tried this for set raw file

 new GifStaticData() {
            @Override
            protected void onPostExecute(Resource drawable) {
                super.onPostExecute(drawable);
                gifImageView.setImageResource(R.raw.earth_tilt_animation);
//                Log.d(TAG, "GIF width is " + gifImageView.getGifWidth());
               // Log.d(TAG, "GIF height is " + gifImageView.getGifHeight());
            }

        }.execute(R.raw.earth_tilt_animation);

GifStaticData.java

public class GifStaticData extends AsyncTask<Resource, Void, Resource> {
  private static final String TAG = "GifDataDownloader";

  @Override protected Resource doInBackground(final Resource... params) {
    final Resource gifUrl = params[0];

    if (gifUrl == null)
      return null;

    try {
//      return ByteArrayHttpClient.get(gifUrl);
      return gifUrl;
    } catch (OutOfMemoryError e) {
      Log.e(TAG, "GifDecode OOM: " + gifUrl, e);
      return null;
    }
  }
}

GifImageView.java

public class GifImageView extends ImageView implements Runnable {

  private static final String TAG = "GifDecoderView";
  private GifDecoder gifDecoder;
  private Bitmap tmpBitmap;
  private final Handler handler = new Handler(Looper.getMainLooper());
  private boolean animating;
  private boolean shouldClear;
  private Thread animationThread;
  private OnFrameAvailable frameCallback = null;
  private long framesDisplayDuration = -1L;
  private OnAnimationStop animationStopCallback = null;

  private final Runnable updateResults = new Runnable() {
    @Override
    public void run() {
      if (tmpBitmap != null && !tmpBitmap.isRecycled()) {
        setImageBitmap(tmpBitmap);
      }
    }
  };

  private final Runnable cleanupRunnable = new Runnable() {
    @Override
    public void run() {
      tmpBitmap = null;
      gifDecoder = null;
      animationThread = null;
      shouldClear = false;
    }
  };

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

  public GifImageView(final Context context) {
    super(context);
  }

  public void setBytes(final byte[] bytes) {
    gifDecoder = new GifDecoder();
    try {
      gifDecoder.read(bytes);
      gifDecoder.advance();
    } catch (final OutOfMemoryError e) {
      gifDecoder = null;
      Log.e(TAG, e.getMessage(), e);
      return;
    }

    if (canStart()) {
      animationThread = new Thread(this);
      animationThread.start();
    }
  }

  public long getFramesDisplayDuration() {
    return framesDisplayDuration;
  }

  /**
   * Sets custom display duration in milliseconds for the all frames. Should be called before {@link
   * #startAnimation()}
   *
   * @param framesDisplayDuration Duration in milliseconds. Default value = -1, this property will
   *                              be ignored and default delay from gif file will be used.
   */
  public void setFramesDisplayDuration(long framesDisplayDuration) {
    this.framesDisplayDuration = framesDisplayDuration;
  }

  public void startAnimation() {
    animating = true;

    if (canStart()) {
      animationThread = new Thread(this);
      animationThread.start();
    }
  }

  public boolean isAnimating() {
    return animating;
  }

  public void stopAnimation() {
    animating = false;

    if (animationThread != null) {
      animationThread.interrupt();
      animationThread = null;
    }
  }

  public void clear() {
    animating = false;
    shouldClear = true;
    stopAnimation();
    handler.post(cleanupRunnable);
  }

  private boolean canStart() {
    return animating && gifDecoder != null && animationThread == null;
  }

  public int getGifWidth() {
    return gifDecoder.getWidth();
  }

  public int getGifHeight() {
    return gifDecoder.getHeight();
  }

  @Override public void run() {
    if (shouldClear) {
      handler.post(cleanupRunnable);
      return;
    }

    final int n = gifDecoder.getFrameCount();
    do {
      for (int i = 0; i < n; i++) {
        if (!animating) {
          break;
        }
        //milliseconds spent on frame decode
        long frameDecodeTime = 0;
        try {
          long before = System.nanoTime();
          tmpBitmap = gifDecoder.getNextFrame();
          frameDecodeTime = (System.nanoTime() - before) / 1000000;
          if (frameCallback != null) {
            tmpBitmap = frameCallback.onFrameAvailable(tmpBitmap);
          }

          if (!animating) {
            break;
          }
          handler.post(updateResults);
        } catch (final ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
          Log.w(TAG, e);
        }
        if (!animating) {
          break;
        }
        gifDecoder.advance();
        try {
          int delay = gifDecoder.getNextDelay();
          // Sleep for frame duration minus time already spent on frame decode
          // Actually we need next frame decode duration here,
          // but I use previous frame time to make code more readable
          delay -= frameDecodeTime;
          if (delay > 0) {
            Thread.sleep(framesDisplayDuration > 0 ? framesDisplayDuration : delay);
          }
        } catch (final Exception e) {
          // suppress any exception
          // it can be InterruptedException or IllegalArgumentException
        }
      }
    } while (animating);
    if (animationStopCallback != null) {
      animationStopCallback.onAnimationStop();
    }
  }

  public OnFrameAvailable getOnFrameAvailable() {
    return frameCallback;
  }

  public void setOnFrameAvailable(OnFrameAvailable frameProcessor) {
    this.frameCallback = frameProcessor;
  }

  public interface OnFrameAvailable {
    Bitmap onFrameAvailable(Bitmap bitmap);
  }

  public OnAnimationStop getOnAnimationStop() {
    return animationStopCallback;
  }

  public void setOnAnimationStop(OnAnimationStop animationStop) {
    this.animationStopCallback = animationStop;
  }

  public interface OnAnimationStop {
    void onAnimationStop();
  }

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    clear();
  }
}

回答1:

I had to play and pause the Gif image Glide - Cannot stop gif onClick- Getting TransitionDrawable instead of Animate/GifDrawable

The idea is to get drawable from view,checking if it is an instance of Gifdrawable and playing and pausing it.(Hoping the gif image is already playing)

Add this In OnClick of GifImageView

Drawable drawable = ((ImageView) v).getDrawable();
if (drawable instanceof GifDrawable) {
         GifDrawable animatable = (GifDrawable) drawable;
         if (animatable.isRunning()) {
                 animatable.stop();
         } else {
                animatable.start();
         }
}


回答2:

I found the solution of above problem using GifMovieView!!!

GifMovieViewer.java

public class GifMovieViewer extends Activity {
    private Button btnStart;
    private GifMovieView gif1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gif_movie_viewer);

        gif1 = (GifMovieView) findViewById(R.id.gif1);
        btnStart = (Button) findViewById(R.id.btnStart);

        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                gif1.setMovieResource(R.drawable.earth_tilt_animation);
                //for pause
                // gif1.setPaused(gif1.isPaused());
            }
        });
    }

    public void onGifClick(View v) {
        GifMovieView gif = (GifMovieView) v;
        gif.setPaused(!gif.isPaused());
    }
}