本人菜鸟,今天看到国外写的android播放gif图片的例子。。与大家分享!也比较简单。类也少就一个! 但是如果gif图片过大(我试过8M),图片边缘就会出现锯齿。如果gif小,那就完全没影响,加载速度也算快! 录制的gif图不太好。
- 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;
-
- /**
- * This is a View class that wraps Android {[url=home.php?mod=space&uid=91636]@link[/url] Movie} object and displays it.
- * You can set GIF as a Movie object or as a resource id from XML or by calling
- * {@link #setMovie(Movie)} or {@link #setMovieResource(int)}.
- * <p>
- * You can pause and resume GIF animation by calling {@link #setPaused(boolean)}.
- * <p>
- * The animation is drawn in the center inside of the measured view bounds.
- *
- * @author Sergey Bakhtiarov
- */
-
- public class GifMovieView extends View {
-
- private static final int DEFAULT_MOVIEW_DURATION = 1000;
-
- private int mMovieResourceId;
- private Movie mMovie;
-
- private long mMovieStart;
- private int mCurrentAnimationTime = 0;
-
- /**
- * Position for drawing animation frames in the center of the view.
- */
- private float mLeft;
- private float mTop;
-
- /**
- * Scaling factor to fit the animation within view bounds.
- */
- private float mScale;
-
- /**
- * Scaled movie frames width and height.
- */
- private int mMeasuredMovieWidth;
- private int mMeasuredMovieHeight;
-
- private volatile boolean mPaused = false;
- private boolean mVisible = true;
-
- public GifMovieView(Context context) {
- this(context, null);
- }
-
- public GifMovieView(Context context, AttributeSet attrs) {
- this(context, attrs, R.styleable.CustomTheme_gifMoviewViewStyle);
- }
-
- public GifMovieView(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) {
-
- /**
- * Starting from HONEYCOMB have to turn off HW acceleration to draw
- * Movie on Canvas.
- */
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
-
- final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GifMoviewView, defStyle,
- R.style.Widget_GifMoviewView);
-
- mMovieResourceId = array.getResourceId(R.styleable.GifMoviewView_gif, -1);
- mPaused = array.getBoolean(R.styleable.GifMoviewView_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;
-
- /**
- * Calculate new movie start time, so that it resumes from the same
- * frame.
- */
- 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();
-
- /*
- * Calculate horizontal scaling
- */
- float scaleH = 1f;
- int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);
-
- if (measureModeWidth != MeasureSpec.UNSPECIFIED) {
- int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);
- if (movieWidth > maximumWidth) {
- scaleH = (float) movieWidth / (float) maximumWidth;
- }
- }
-
- /*
- * calculate vertical scaling
- */
- float scaleW = 1f;
- int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec);
-
- if (measureModeHeight != MeasureSpec.UNSPECIFIED) {
- int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);
- if (movieHeight > maximumHeight) {
- scaleW = (float) movieHeight / (float) maximumHeight;
- }
- }
-
- /*
- * calculate overall scale
- */
- mScale = 1f / Math.max(scaleH, scaleW);
-
- mMeasuredMovieWidth = (int) (movieWidth * mScale);
- mMeasuredMovieHeight = (int) (movieHeight * mScale);
-
- setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);
-
- } else {
- /*
- * No movie set, just set minimum available size.
- */
- setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- /*
- * Calculate left / top for drawing in center
- */
- 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);
- }
- }
- }
-
- /**
- * Invalidates view only if it is visible.
- * <br>
- * {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher.
- *
- */
- @SuppressLint("NewApi")
- private void invalidateView() {
- if(mVisible) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- postInvalidateOnAnimation();
- } else {
- invalidate();
- }
- }
- }
-
- /**
- * Calculate current animation time
- */
- private void updateAnimationTime() {
- long now = android.os.SystemClock.uptimeMillis();
-
- if (mMovieStart == 0) {
- mMovieStart = now;
- }
-
- int dur = mMovie.duration();
-
- if (dur == 0) {
- dur = DEFAULT_MOVIEW_DURATION;
- }
-
- mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
- }
-
- /**
- * Draw current GIF frame
- */
- 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();
- }
- }
-
复制代码
布局文件
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- <font color="#ff0000"> xmlns:custom="http://schemas.android.com/apk/res-auto"</font>
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".MainActivity" >
- <com.basv.gifmoviewview.widget.GifMovieView
- android:id="@+id/gif"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:layout_centerInParent="true"
- <font color="#ff0000"> android:onClick="onGifClick"
- custom:gif="@drawable/gif_005"</font> />
-
- </RelativeLayout>
-
复制代码
values/attrs.xml
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="GifMoviewView">
- <attr name="gif" format="reference" />
- <attr name="paused" format="boolean" />
- </declare-styleable>
- <declare-styleable name="CustomTheme">
- <attr name="gifMoviewViewStyle" format="reference" />
- </declare-styleable>
- </resources>
复制代码
在values/styles里加上 <style name="Widget.GifMoviewView" parent="@android:style/Widget"></style> 接下来是Activity
- public class MainActivity extends Activity {
-
- GifMovieView gif;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- gif= (GifMovieView) findViewById(R.id.gif);
- //可以动态添加
- // gif.setMovieResource(R.drawable.gif_005);
- }
- /*
- * 点击gif让其暂停或开始。
- * 如果不想要可以去掉xml中的onClick属性
- */
- public void onGifClick(View v) {
- GifMovieView gif = (GifMovieView) v;
- gif.setPaused(!gif.isPaused());
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
-
- }
复制代码
|