Android自定义GifView显示gif动画

jopen 10年前

  gif动画在web开发中使用的非常的多,利用gif,许多动画不必再用程序编写,现在有非常多的App已经使用到了gif动画,可是android sdk并没有为我们提供gif这种View,所以我们只能自定义一个View,去实现gif效果.

   android虽然没有为我们提供现成的GifView,但是为我们提供了Movie类,这个类就是用来实现GifView的关键类.它主要有两个最重要的方法,一个是根据动画播放时间设置当前要现显示的帧,二是将当前要显示的帧绘制到画布中.下面看一下效果图:

点击暂停按钮还可以暂停gif动画.

   下面就看是如何实现的:

    1.首先将需要用到的属性先自定义好:如下代码所示:

    <?xml version="1.0" encoding="utf-8"?>        <resources>                    <declare-styleable name="gifCommon">                <attr name="gif_src" format="reference" />                <attr name="decode_stream" format="boolean" />                <attr name="default_animation_time" format="integer" />            </declare-styleable>                </resources>  

三个属性分别代表:gif资源,是否采用流编码,默认动画间隔时间.    2.自定义GifView代码.
    package view;                import java.io.ByteArrayOutputStream;        import java.io.InputStream;                import android.content.Context;        import android.content.res.TypedArray;        import android.graphics.Canvas;        import android.graphics.Movie;        import android.util.AttributeSet;        import android.view.View;                import com.example.drawbaledemo.R;                /**        * @author rzq        *        */        public class GifView extends View {                    private Movie mMovie;                /**                * 动画开始时间                /               private long mMovieStart;           private boolean mPaused = false;               /**                * 当前帧动画时间                /               private int mCurrentAnimationTime ;           /**                * 自定义的三个属性                /               private boolean decode_STREAM;           private int src_ID;           private int default_time;                  public GifView(Context context) {               super(context);               init(context, null);           }                  public GifView(Context context, AttributeSet set) {               super(context, set);               init(context, set);           }                  private void init(Context context, AttributeSet set) {                      TypedArray a = context.obtainStyledAttributes(set,                       R.styleable.gifCommon);               src_ID = a.getResourceId(R.styleable.gifCommon_gif_src, -1);               decode_STREAM = a.getBoolean(R.styleable.gifCommon_decode_stream, true);               default_time = a.getInteger(                       R.styleable.gifCommon_default_animation_time, 1000);               a.recycle();                      setFocusable(true);               java.io.InputStream is;               is = context.getResources().openRawResource(src_ID);                      if (decode_STREAM) {                   mMovie = Movie.decodeStream(is);    // 根据文件流创建Movier绘制对象               } else {                   byte[] array = streamToBytes(is);                   mMovie = Movie.decodeByteArray(array, 0, array.length);               }           }                  @Override           protected void onDraw(Canvas canvas) {               if (mMovie != null) {                   if (!mPaused) {                       // 更新帧时间                       updateAnimationTime();                       drawMovieFrame(canvas);                       invalidate();                   } else {                       // 暂停时,不更新帧时间,则只画当前帧                       drawMovieFrame(canvas);                   }               }           }                  private void updateAnimationTime() {               long now = android.os.SystemClock.uptimeMillis();               // 如果第一帧,记录起始时间               if (mMovieStart == 0) {                   mMovieStart = now;               }               // 取出动画的时长               int dur = mMovie.duration();               if (dur == 0) {                   dur = default_time;               }               // 算出需要显示第几帧               mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);           }                  private void drawMovieFrame(Canvas canvas) {               // 设置要显示的帧,绘制即可               mMovie.setTime(mCurrentAnimationTime);               canvas.save(Canvas.MATRIX_SAVE_FLAG);               mMovie.draw(canvas, 0, 0);               canvas.restore();           }                  /**            * 设置暂停            *             * @param paused            */            public void setPaused(boolean paused) {                this.mPaused = paused;                if (!paused) {                    /**                    * 更新动画起点时间                    */                    mMovieStart = android.os.SystemClock.uptimeMillis()                            - mCurrentAnimationTime;                }                invalidate();            }                    /**            * 判断gif图是否停止了            *             * @return            */            public boolean isPaused() {                return this.mPaused;            }                    /**            * 重写此方法,使自定义View支持wrap_content            */            @Override            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {                int widthMode = MeasureSpec.getMode(widthMeasureSpec);                int widthSize = MeasureSpec.getSize(widthMeasureSpec);                int heightMode = MeasureSpec.getMode(heightMeasureSpec);                int heightSize = MeasureSpec.getSize(heightMeasureSpec);                int width;                int height;                if (widthMode == MeasureSpec.EXACTLY) {                    width = widthSize;                } else {                            int desired = (int) (getPaddingLeft() + mMovie.width() + getPaddingRight());                    width = Math.min(desired,widthSize);                }                        if (heightMode == MeasureSpec.EXACTLY) {                    height = heightSize;                } else {                    int desired = (int) (getPaddingTop() + mMovie.height() + getPaddingBottom());                    height = Math.min(desired,heightSize);                }                        setMeasuredDimension(width, height);            }                    /**            * 将流转化为字节数组            *             * @param is            * @return            */            private static byte[] streamToBytes(InputStream is) {                ByteArrayOutputStream os = new ByteArrayOutputStream(1024);                byte[] buffer = new byte[1024];                int len;                try {                    while ((len = is.read(buffer)) >= 0) {                        os.write(buffer, 0, len);                    }                } catch (java.io.IOException e) {                }                return os.toByteArray();            }                }  
  3.布局文件中使用GifView.
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"            xmlns:tools="http://schemas.android.com/tools"            xmlns:gif="http://schemas.android.com/apk/res-auto"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:background="#fed952"            android:gravity="center" >                    <view.GifView                android:id="@+id/gif_view"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:background="#ffffff"                gif:decode_stream="true"                gif:default_animation_time="1000"                gif:gif_src="@drawable/animated_gif" />                    <TextView                android:id="@+id/btn"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_below="@+id/gif_view"                android:text="暂停" />                </RelativeLayout>  

与使用普通的View一样,将需要的资源传入即可.

来自:http://blog.csdn.net/lcq5211314123/article/details/43492509