I used Movie class to display animated GIF according to this page. Below is the class I created to diaplay the gif and method invoking it.
It is deprecated from SDK 28 and AnimatedImageView is recommended. I used both and it turned out to me that old, unofficial way (with Movie) is faster and more reliable (AnimatedImageView hangs freezes sometimes).
Class to display animiated GIF with Movie
public class ShowGifView extends View {
private Movie movie;
private int gifImageDrawableId;
private final Context ctx;
private long gifStart = 0;
public ShowGifView(Context context) {
super(context);
// Make the custom view focus.
setFocusable(true);
ctx = context;
}
@Override
protected void onDraw(Canvas canvas) {
long now = System.currentTimeMillis();
if (gifStart == 0) {
gifStart = now;
}
if (movie != null) {
// Get gif movie duration time.
int duration = movie.duration();
if (duration == 0) {
duration = 1000;
}
// Get played frame percentage.
int relTime = (int)((now - gifStart) % duration);
// Set current gif frame time.
movie.setTime(relTime);
// Get custom view width and height.
int width = this.getWidth();
int height = this.getHeight();
// Get gif image width and height.
int movieWidth = movie.width();
int movieHeight = movie.height();
// Scale canvas size to fit the custom view.
canvas.scale((float)width / movieWidth, (float)height / movieHeight);
// Draw the gif image frame to custom view canvas.
movie.draw(canvas, 1, 1);
// This method will invoke onDraw method.
invalidate();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(movie != null){
int scale = heightMeasureSpec / movie.height();
setMeasuredDimension(movie.width() * scale, movie.height() * scale);
}else{
setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
}
}
public int getGifImageDrawableId() {
return gifImageDrawableId;
}
public void setGifImageDrawableId(int gifImageDrawableId) {
this.gifImageDrawableId = gifImageDrawableId;
}
// Call this method to read the drawable gif image to create movie object.
public void drawGif() {
Resources resources = ctx.getResources();
InputStream inputStream = resources.openRawResource(gifImageDrawableId);
movie = Movie.decodeStream(inputStream);
// Invalidate the view and invoke onDraw method.
invalidate();
}
}
Method invoking this:
private View addAnimatedGif(ConstraintLayout lout, int animatedGif) {
ShowGifView resultView = new ShowGifView(getApplicationContext());
// Set Layer type to display animated GIF on all APIs
resultView.setLayerType(View.LAYER_TYPE_SOFTWARE, new Paint());
resultView.setGifImageDrawableId(animatedGif);
resultView.drawGif();
ConstraintSet cSet = new ConstraintSet();
lout.addView(resultView);
resultView.setId(View.generateViewId());
int id = resultView.getId();
cSet.clone(lout);
cSet.connect(id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 0);
cSet.connect(id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);
cSet.connect(id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);
cSet.connect(id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0);
cSet.applyTo(lout);
return resultView;
}