当前位置: 首页 > 工具软件 > GifView > 使用案例 >

GifView实现笔记,真正的成功实现Gif播放

汪欣德
2023-12-01

GifView实现笔记,真正的成功实现Gif播放

本文属于记录学习实现GifView播放gif图片,由于时间久,已经忘记了是向哪个大神写的文章学习的了,现将源码贴出来,一作个人笔记用,二作为技术共享,供学习交流用。源码如下:

GIFView.java

package com.sage.org.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;

import com.sage.org.R;
/**

  • 用来显示Gif图片的
    */
    public class GifView extends View {

    private static final int DEFAULT_MOVIE_DURATION = 1000;

    private int mMovieResourceId;

    private Movie mMovie;

    private long mMovieStart;

    private int mCurrentAnimationTime = 0;

    private float mLeft;

    private float mTop;

    private float mScale;

    private int mMeasuredMovieWidth;

    private int mMeasuredMovieHeight;

    private boolean mVisible = true;

    private volatile boolean mPaused = false;

    public GifView(Context context) {
    this(context, null);
    }

    public GifView(Context context, AttributeSet attrs) {
    this(context, attrs, R.styleable.CustomTheme_gifViewStyle);
    }

    public GifView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setViewAttributes(context, attrs, defStyle);
    }

    @SuppressLint(“NewApi”)
    private void setViewAttributes(Context context, AttributeSet attrs,
    int defStyle) {
    setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    final TypedArray array = context.obtainStyledAttributes(attrs,
    R.styleable.GifView, defStyle, R.style.Widget_GifView);
    mMovieResourceId = array.getResourceId(R.styleable.GifView_gif, -1);
    mPaused = array.getBoolean(R.styleable.GifView_paused, false);
    array.recycle();
    if (mMovieResourceId != -1) {
    mMovie = Movie.decodeStream(getResources().openRawResource(
    mMovieResourceId));
    }
    }

    public void setMovieResource(int movieResId) {
    this.mMovieResourceId = movieResId;
    mMovie = Movie.decodeStream(getResources().openRawResource(
    mMovieResourceId));
    requestLayout();
    }

    public void setMovie(Movie movie) {
    this.mMovie = movie;
    requestLayout();
    }

    public Movie getMovie() {
    return mMovie;
    }

    public void setMovieTime(int time) {
    mCurrentAnimationTime = time;
    invalidate();
    }

    public void setPaused(boolean paused) {
    this.mPaused = paused;
    if (!paused) {
    mMovieStart = android.os.SystemClock.uptimeMillis()
    - mCurrentAnimationTime;
    }
    invalidate();
    }

    public boolean isPaused() {
    return this.mPaused;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (mMovie != null) {
    int movieWidth = mMovie.width();
    int movieHeight = mMovie.height();
    int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);
    float scaleW = (float) movieWidth / (float) maximumWidth;
    mScale = 1f / scaleW;
    mMeasuredMovieWidth = maximumWidth;
    mMeasuredMovieHeight = (int) (movieHeight * mScale);
    setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);
    } else {
    setMeasuredDimension(getSuggestedMinimumWidth(),
    getSuggestedMinimumHeight());
    }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    mLeft = (getWidth() - mMeasuredMovieWidth) / 2f;
    mTop = (getHeight() - mMeasuredMovieHeight) / 2f;
    mVisible = getVisibility() == View.VISIBLE;
    }

    @Override
    protected void onDraw(Canvas canvas) {
    if (mMovie != null) {
    if (!mPaused) {
    updateAnimationTime();
    drawMovieFrame(canvas);
    invalidateView();
    } else {
    drawMovieFrame(canvas);
    }
    }
    }

    @SuppressLint(“NewApi”)
    private void invalidateView() {
    if (mVisible) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    postInvalidateOnAnimation();
    } else {
    invalidate();
    }
    }
    }

    private void updateAnimationTime() {
    long now = android.os.SystemClock.uptimeMillis();
    if (mMovieStart == 0) {
    mMovieStart = now;
    }
    int dur = mMovie.duration();
    if (dur == 0) {
    dur = DEFAULT_MOVIE_DURATION;
    }
    mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
    }

    private void drawMovieFrame(Canvas canvas) {
    mMovie.setTime(mCurrentAnimationTime);
    canvas.save(Canvas.MATRIX_SAVE_FLAG);
    canvas.scale(mScale, mScale);
    mMovie.draw(canvas, mLeft / mScale, mTop / mScale);
    canvas.restore();
    }

    @SuppressLint(“NewApi”)
    @Override
    public void onScreenStateChanged(int screenState) {
    super.onScreenStateChanged(screenState);
    mVisible = screenState == SCREEN_STATE_ON;
    invalidateView();
    }

    @SuppressLint(“NewApi”)
    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    mVisible = visibility == View.VISIBLE;
    invalidateView();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
    super.onWindowVisibilityChanged(visibility);
    mVisible = visibility == View.VISIBLE;
    invalidateView();
    }
    }

还需要attrs.xml里面添加:

<declare-styleable name="GifView">
    <attr name="gif" format="reference" />
    <attr name="paused" format="boolean" />
</declare-styleable>
<declare-styleable name="CustomTheme">
    <attr name="gifViewStyle" format="reference" />
</declare-styleable>
<style name="Widget.GifView" parent="@android:style/Widget" />

界面引用:
//注意: 替换inputstream为实际的gif,引用即时的context,将GifView添加到容器组件
Movie movie = Movie.decodeStream(inpustream);
GifView gifView = new GifView(context);
gifView.setPaused(false);
gifView.setMovie(movie);

布局引用:
// 将gif_1替换为实际的gif图片
<com.vogtec.sdk.ui.view.GifView
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
app:gif="@raw/gif_1"
app:paused=“false”
/>

 类似资料: