Android学习之ImageView放置gif动态图

在Android开发中,遇到在ImageView中显示动态图的问题,常见的解决方案包括将gif分解播放、使用开源库和自定义ImageView通过Movie类播放。自定义的方案可能在处理大图时遭遇OOM问题,需要对图片大小进行控制。

最近做图片的时候碰到一个问题,就是imageview控件中放动态图,显示出来的效果跟静态图是一样的。于是我网上大概找了一下资料,对于这方面大概有三个解决方法
一、将gif用工具分割,一帧一帧的播放

这篇博客中有介绍http://www.cnblogs.com/TerryBlog/archive/2010/09/06/1819641.html

二、使用开源框架

Glide是个不错的选择,当然也还有其他的,下面这篇博客,对于Glide讲的还比较清晰
http://blog.csdn.net/fancylovejava/article/details/44747759

三、自定义imageview,使用Movie来播放

好了,对于这个,我亲手做了个demo,注解还算全
由于是要自定义控件,我们还可能会用到一些自定义的属性,因此在values目录下新建一个attrs.xml的文件,可以在这个文件中添加任何需要自定义的属性。这里我们目前只需要一个auto_play属性,代码如下所示:
<declare-styleable name="MyImageView">
        <attr name="auto_play" format="boolean">

        </attr>
    </declare-styleable>

这个写好了,接下来我们要写一个类来继承imageview或view

package com.jp.tools;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;

import com.jp.activity.R;

import java.io.InputStream;
import java.lang.reflect.Field;

/**
 * Created by Administrator on 2015/8/21.
 */
public class MyImageView extends ImageView implements View.OnClickListener
{


    /**
     * 播放GIF动画的关键类
     */
    private Movie mMovie;
    /**
     * 控制播放的按钮
     */
    private Bitmap mStartButton;

    /**
     * 记录动画开始的时间
     */
    private long mMovieStart;

    /**
     * GIF图片的宽度
     */
    private int mImageWidth;

    /**
     * GIF图片的高度
     */
    private int mImageHeight;

    /**
     * 图片是否正在播放
     */
    private boolean isPlaying;

    /**
     * 是否允许自动播放
     */
    private boolean isAutoPlay;

    public MyImageView(Context context)
    {
        super(context);
        Log.e("ten", "72");
    }

    public MyImageView(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
        Log.e("ten", "73");
    }

    public MyImageView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);

        setImageResLoad(context, attrs, defStyleAttr);



    }

    private void setImageResLoad(Context context, AttributeSet attrs, int defStyleAttr)
    {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyImageView);
        Log.e("ten", "1 ");
        int resourceID = getResourcesID(typedArray);
        typedArray.recycle();
        if (resourceID != 0) {
            Log.e("ten", "2 ");

            InputStream inputStream = getResources().openRawResource(resourceID);

            //对图片进行解码
            mMovie = Movie.decodeStream(inputStream);
            if (mMovie != null) {
                Log.e("ten", "3 ");
                // 如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
                isAutoPlay = typedArray.getBoolean(R.styleable.MyImageView_auto_play, false);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                mImageWidth = bitmap.getWidth();
                mImageHeight = bitmap.getHeight();
                bitmap.recycle();
                if (!isAutoPlay) {
                    // 当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
                    mStartButton = BitmapFactory.decodeResource(getResources(),
                            R.drawable.ic_launcher);
                    setOnClickListener(this);
                }
            }

        }
    }

    /**
     * 通过Java反射,获取src指定图片资源所对应的id。
     */
    public int getResourcesID(TypedArray typedArray)
    {
        Log.e("ten", "4 ");
        try {
            Field field = TypedArray.class.getDeclaredField("mValue");
            field.setAccessible(true);
            TypedValue typedValueObject = (TypedValue) field.get(typedArray);
            return typedValueObject.resourceId;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (typedArray != null) {
                typedArray.recycle();
            }
        }
        return 0;
    }


    @Override
    public void onClick(View v)
    {
        Log.e("ten", "5 ");
        if (v.getId() == getId()) {
            //点击图片开始播放
            isPlaying = true;
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        Log.e("ten", "6");
        if (mMovie == null) {
            Log.e("ten", "7b");
            // mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
            super.onDraw(canvas);

        } else {
            Log.e("ten", "7c");
            //如果mMovie不等于null,那就说明是gif图片
            if (isAutoPlay) {
                Log.e("ten", "7d");
                //如果允许播放,调用palyMovie();
                playMovie(canvas);
                invalidate();
            } else {
                Log.e("ten", "7e");
                //不允许自动播放,判断是否要播放
                if (isPlaying) {
                    if (playMovie(canvas)) {
                        isPlaying = false;
                        Log.e("ten", "7f");
                    }
                    invalidate();
                } else {
                    // 还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮
                    Log.e("ten", "g");
                    mMovie.setTime(0);
                    mMovie.draw(canvas, 0, 0);
                    int imageX = (mImageWidth - mStartButton.getWidth()) / 2;
                    int imageY = (mImageHeight - mStartButton.getHeight()) / 2;
                    canvas.drawBitmap(mStartButton, imageX, imageY, null);

                }
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.e("ten", "onMeasure_1");
        if (mMovie != null) {
            Log.e("ten", "onMeasure_2");
            // 如果是GIF图片则重写设定myImageView的大小
            setMeasuredDimension(mImageWidth, mImageHeight);
        }
    }
 /**  
     * 开始播放GIF动画,播放完成返回true,未完成返回false。  
     *   
     * @param canvas  
     * @return 播放完成返回true,未完成返回false。  
     */ 
    public boolean playMovie(Canvas canvas)
    {
        Log.e("ten", "playMovie_1");
        long now = SystemClock.uptimeMillis();
        if (mMovieStart == 0) {
            mMovieStart = now;
        }
        int duration = mMovie.duration();
        if (duration == 0) {
            duration = 1000;
        }
        int loadTime = (int) ((now - mMovieStart) % duration);
        mMovie.setTime(loadTime);
        mMovie.draw(canvas, 0, 0);
        if ((now - mMovieStart) >= duration) {
            mMovieStart = 0;
            return true;
        }
        return false;
    }
}

布局的代码:

<com.jp.tools.MyImageView

        android:src="@drawable/pic_four"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        attr:auto_play="true"
        />
    <!--设置attr:auto_play="true"动态图就会自动播放,如果不设置,或未false图片就需要点了之后才播放 -->

效果图(哈哈,还是很萌的妹纸吧):
这里写图片描述
对了,还有一点需要说一下,这种方法的实现当gif图片过大的时候会报oom。所以对于图片的大小要注意一下。

希望大家多多交流,有什么更好的实现方法

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值