android 自定义控件gif压缩包,Android实现可播放GIF动画的ImageView

Android的原生控件并不支持播放GIF格式的图片。我们都知道,在Android中如果想要显示一张图片,可以借助ImageView来完成,但是如果将一张GIF图片设置到ImageView里,它只会显示这张图片的第一帧,不会产生任何的动画效果。今天我们来编写一个自定义的增强型ImageView(继承ImageView),可以播放GIF格式的图片,暂且叫做GifImageView吧。

1.自定义属性

2.自定义View中获取属性值

private Movie mMovie;//播放动画需要用到的,系统类

private int mImageWidth;//动画的imageview的宽度

private int mImageHeight;//动画imageview的高度

private long mMovieStart = 0;// 播放开始

private boolean isAutoPlay;//是否自动播放

private Bitmap mStartPlay;//开始按钮

private boolean isPlaying=false;//记录是否正在播放

private float mScale;//图片的缩放比

private int mMeasuredGifWidth;//缩放后图片宽

private int mMeasuredGifHeight;//缩放后图片高

...

private void init(Context context, AttributeSet attrs) {

TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.GifImageView);

// 通过反射拿布局中src的资源id,所以gif文件需要放在布局的src中

int resourceId = getResourceId(attributes, context, attrs);

if (resourceId != 0) {

// 说明是gif动画

// 1.将resourcesId变成流

// 2.用Move来decode解析流

// 3.获得bitmap的长宽

InputStream is = getResources().openRawResource(resourceId);

mMovie = Movie.decodeStream(is);

if (mMovie != null) {

Bitmap bitmap = BitmapFactory.decodeStream(is);

mImageWidth = bitmap.getWidth();

mImageHeight = bitmap.getHeight();

// 用完释放

bitmap.recycle();

// 获得是否允许自动播放,如果不允许自动播放,则初始化播放按钮

isAutoPlay = attributes.getBoolean(R.styleable.GifImageView_auto_play, false);

if (!isAutoPlay) {

mStartPlay = BitmapFactory.decodeResource(getResources(),R.drawable.start_play);

setOnClickListener(this);

}

}

}

//回收资源

attributes.recycle();

}

/**

* 通过反射拿布局中src的资源id

*

* @param attrs

* @param context

* @param attributes

*/

private int getResourceId(TypedArray attributes, Context context, AttributeSet attrs) {

try {

Field filed = TypedArray.class.getDeclaredField("mValue");

filed.setAccessible(true);

TypedValue typeValue = (TypedValue) filed.get(attributes);

return typeValue.resourceId;

} catch (Exception e) {

e.printStackTrace();

}

}

return 0;

}

3.重写onMesure()

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

if (mMovie != null) {

/*

* Calculate horizontal scaling

*/

float scaleW = 1f;

int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);

if (measureModeWidth != MeasureSpec.UNSPECIFIED) {

int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);

scaleW = (float) mImageWidth / (float) maximumWidth;

}

/*

* calculate vertical scaling

*/

float scaleH = 1f;

int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec);

if (measureModeHeight != MeasureSpec.UNSPECIFIED) {

int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);

scaleH = (float) mImageHeight / (float) maximumHeight;

}

/*

* calculate overall scale

*/

mScale = 1f / Math.max(scaleH, scaleW);

mMeasuredGifWidth = (int) (mImageWidth * mScale);

mMeasuredGifHeight = (int) (mImageHeight * mScale);

setMeasuredDimension(mMeasuredGifWidth, mMeasuredGifHeight);

}

}

4.重写onDraw()

@Override

protected void onDraw(Canvas canvas) {

if (mMovie == null) {

// mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法

super.onDraw(canvas);

} else {

// mMovie不等于null,说明是张GIF图片

if (isAutoPlay) {

// 如果允许自动播放,就播放

playMovie(canvas);

invalidate();

} else {

// 不允许自动播放的话

// 1.判断是否正在播放

// 2.获得第一帧的图像

// 3.然后添加播放按钮

if (isPlaying) {

// 如果正在播放就playmoive继续播放

if (playMovie(canvas)) {

isPlaying = false;

}

invalidate();

} else {

// 第一帧

mMovie.setTime(0);

canvas.save(Canvas.MATRIX_SAVE_FLAG);

canvas.scale(mScale, mScale);

mMovie.draw(canvas, 0, 0);// 画

canvas.restore();

// 绘制开始按钮

int offsetW = (mMeasuredGifWidth - mStartPlay.getWidth()) / 2;

int offsetH = (mMeasuredGifHeight - mStartPlay.getHeight()) / 2;

canvas.drawBitmap(mStartPlay, offsetW, offsetH, null);

}

}

}

}

/**

* 播放gif动画

*

* @param canvas

*/

private boolean playMovie(Canvas canvas) {

// 1.获取播放的时间

// 2.如果开始start=0,则认为是开始

// 3.记录播放的时间

// 4.设置进度

// 5.画动画

// 6.如果时间大于了播放的时间,则证明结束

long now = SystemClock.uptimeMillis();

if (mMovieStart == 0) {

mMovieStart = now;

}

int duration = mMovie.duration();

if (duration == 0) {

duration = 1000;

}

//记录gif播放了多少时间

int relTime = (int) ((now - mMovieStart) % duration);

mMovie.setTime(relTime);// 设置时间

canvas.save(Canvas.MATRIX_SAVE_FLAG);

canvas.scale(mScale, mScale);

mMovie.draw(canvas, 0, 0);// 画

canvas.restore();

if ((now - mMovieStart) >= duration) {

// 结束

mMovieStart = 0;

return true;

}

return false;

}

5.添加点击事件

@Override

public void onClick(View v) {

if(v.getId()==getId()){

isPlaying=true;

invalidate();

}

}

还有一点需要注意,有些4.0以上系统的手机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁用硬件加速功能,可以通过指定android:hardwareAccelerated=false来完成。

--------------------------------------------------------------------------------

现在我们来看看运行后效果如何吧,

布局文件:

xmlns:tools="http://schemas.android.com/tools"

xmlns:attr="http://schemas.android.com/apk/res/com.hx.gifimageview"

android:id="@+id/container"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:layout_width="150dip"

android:layout_height="150dip"

android:layout_margin="10dp"

android:src="@drawable/shulan"

attr:auto_play="false" />

android:layout_width="150dip"

android:layout_height="150dip"

android:layout_margin="10dp"

android:src="@drawable/shulan"

attr:auto_play="true" />

android:layout_width="150dip"

android:layout_height="150dip"

android:layout_margin="10dp"

android:src="@drawable/jingtai"

attr:auto_play="true" />

图一的auto_play属性为false,会显示第一帧和一个播放按钮,点击后Gif图片会自动运行。

图二的auto_play属性为true,会自动循环播放Gif。

图三我们给的资源是静态图片,因为自定义View继承ImageView,所以具备ImageView所有特性,因此也能显示静态图片。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值