package frezc.loadingdemo.app2; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Movie; import android.graphics.Paint; import android.graphics.Rect; import android.os.SystemClock; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * Created by freeze on 2015/4/26. */ public class GifView extends SurfaceView implements SurfaceHolder.Callback{ private SurfaceHolder holder; private DrawThread drawThread = new DrawThread(); private Movie movie; private int resId; private long movieStartTime = -1; private float scale; private int measuredMovieWidth; private int measuredMovieHeight; private float left,top; public GifView(Context context) { this(context, null); } public GifView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.GifView); resId = ta.getResourceId(R.styleable.GifView_src, R.drawable.dance); ta.recycle(); holder = getHolder(); holder.addCallback(this); movie = Movie.decodeStream(getResources().openRawResource(resId)); drawThread.setDaemon(true); } @Override public void surfaceCreated(SurfaceHolder holder) { drawThread.running=true; drawThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { drawThread.running = false; movieStartTime = -1; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if(movie != null){ int movieWidth = movie.width(); int movieHeight = movie.height(); int maximumWidth = MeasureSpec.getSize(widthMeasureSpec); float scaleW = (float) movieWidth / (float) maximumWidth; scale = 1f / scaleW; measuredMovieWidth = maximumWidth; measuredMovieHeight = (int) (movieHeight * scale); setMeasuredDimension(measuredMovieWidth, measuredMovieHeight); }else { setMeasuredDimension(getSuggestedMinimumWidth(),getSuggestedMinimumHeight()); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); this.left = (getMeasuredWidth() - measuredMovieWidth) / 2f; this.top = (getMeasuredHeight() - measuredMovieHeight) / 2f; } private void drawMovieFrame(Canvas canvas) { if(canvas == null) return; long now = SystemClock.uptimeMillis(); if(movieStartTime == -1){ movieStartTime = now; } int duration = movie.duration(); if(duration == 0){ duration = 1000; } int currentAnimTime = (int) ((now - movieStartTime) % duration); movie.setTime(currentAnimTime); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(scale, scale); movie.draw(canvas, left / scale, top / scale); canvas.restore(); } class DrawThread extends Thread{ Canvas canvas; boolean running; @Override public void run() { while (running && holder != null){ canvas = holder.lockCanvas(); drawMovieFrame(canvas); holder.unlockCanvasAndPost(canvas); try { sleep(16); } catch (InterruptedException e) { e.printStackTrace(); } } } } }