最近做图片的时候碰到一个问题,就是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。所以对于图片的大小要注意一下。
希望大家多多交流,有什么更好的实现方法
在Android开发中,遇到在ImageView中显示动态图的问题,常见的解决方案包括将gif分解播放、使用开源库和自定义ImageView通过Movie类播放。自定义的方案可能在处理大图时遭遇OOM问题,需要对图片大小进行控制。

2696

被折叠的 条评论
为什么被折叠?



