android自定义GifView显示gif动画

gif动画在web开发中使用的非常的多,利用gif,许多动画不必再用程序编写,现在有非常多的App已经使用到了gif动画,可是android sdk并没有为我们提供gif这种View,所以我们只能自定义一个View,去实现gif效果.

android虽然没有为我们提供现成的GifView,但是为我们提供了Movie类,这个类就是用来实现GifView的关键类.它主要有两个最重要的方法,一个是根据动画播放时间设置当前要现显示的帧,二是将当前要显示的帧绘制到画布中.下面看一下效果图:

点击暂停按钮还可以暂停gif动画.

下面就看是如何实现的:

1.首先将需要用到的属性先自定义好:如下代码所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="gifCommon">
        <attr name="gif_src" format="reference" />
        <attr name="decode_stream" format="boolean" />
        <attr name="default_animation_time" format="integer" />
    </declare-styleable>

</resources>

三个属性分别代表:gif资源,是否采用流编码,默认动画间隔时间.

2.自定义GifView代码.

package view;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.view.View;

import com.example.drawbaledemo.R;

/**
 * @author rzq
 *
 */
public class GifView extends View {

	private Movie mMovie;
        /**
         * 动画开始时间
         /
        private long mMovieStart;
	private boolean mPaused = false;
        /**
         * 当前帧动画时间
         /
        private int mCurrentAnimationTime ;
	/**
         * 自定义的三个属性
         /
        private boolean decode_STREAM;
	private int src_ID;
	private int default_time;

	public GifView(Context context) {
		super(context);
		init(context, null);
	}

	public GifView(Context context, AttributeSet set) {
		super(context, set);
		init(context, set);
	}

	private void init(Context context, AttributeSet set) {

		TypedArray a = context.obtainStyledAttributes(set,
				R.styleable.gifCommon);
		src_ID = a.getResourceId(R.styleable.gifCommon_gif_src, -1);
		decode_STREAM = a.getBoolean(R.styleable.gifCommon_decode_stream, true);
		default_time = a.getInteger(
				R.styleable.gifCommon_default_animation_time, 1000);
		a.recycle();

		setFocusable(true);
		java.io.InputStream is;
		is = context.getResources().openRawResource(src_ID);

		if (decode_STREAM) {
			mMovie = Movie.decodeStream(is);    // 根据文件流创建Movier绘制对象
		} else {
			byte[] array = streamToBytes(is);
			mMovie = Movie.decodeByteArray(array, 0, array.length);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		if (mMovie != null) {
			if (!mPaused) {
				// 更新帧时间
				updateAnimationTime();
				drawMovieFrame(canvas);
				invalidate();
			} else {
				// 暂停时,不更新帧时间,则只画当前帧
				drawMovieFrame(canvas);
			}
		}
	}

	private void updateAnimationTime() {
		long now = android.os.SystemClock.uptimeMillis();
		// 如果第一帧,记录起始时间
		if (mMovieStart == 0) {
			mMovieStart = now;
		}
		// 取出动画的时长
		int dur = mMovie.duration();
		if (dur == 0) {
			dur = default_time;
		}
		// 算出需要显示第几帧
		mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
	}

	private void drawMovieFrame(Canvas canvas) {
		// 设置要显示的帧,绘制即可
		mMovie.setTime(mCurrentAnimationTime);
		canvas.save(Canvas.MATRIX_SAVE_FLAG);
		mMovie.draw(canvas, 0, 0);
		canvas.restore();
	}

	/**
	 * 设置暂停
	 *
	 * @param paused
	 */
	public void setPaused(boolean paused) {
		this.mPaused = paused;
		if (!paused) {
			/**
			 * 更新动画起点时间
			 */
			mMovieStart = android.os.SystemClock.uptimeMillis()
					- mCurrentAnimationTime;
		}
		invalidate();
	}

	/**
	 * 判断gif图是否停止了
	 *
	 * @return
	 */
	public boolean isPaused() {
		return this.mPaused;
	}

	/**
	 * 重写此方法,使自定义View支持wrap_content
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
		int width;
		int height;
		if (widthMode == MeasureSpec.EXACTLY) {
			width = widthSize;
		} else {

			int desired = (int) (getPaddingLeft() + mMovie.width() + getPaddingRight());
			width = Math.min(desired,widthSize);
		}

		if (heightMode == MeasureSpec.EXACTLY) {
			height = heightSize;
		} else {
			int desired = (int) (getPaddingTop() + mMovie.height() + getPaddingBottom());
			height = Math.min(desired,heightSize);
		}

		setMeasuredDimension(width, height);
	}

	/**
	 * 将流转化为字节数组
	 *
	 * @param is
	 * @return
	 */
	private static byte[] streamToBytes(InputStream is) {
		ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
		byte[] buffer = new byte[1024];
		int len;
		try {
			while ((len = is.read(buffer)) >= 0) {
				os.write(buffer, 0, len);
			}
		} catch (java.io.IOException e) {
		}
		return os.toByteArray();
	}

}

3.布局文件中使用GifView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:gif="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fed952"
    android:gravity="center" >

    <view.GifView
        android:id="@+id/gif_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        gif:decode_stream="true"
        gif:default_animation_time="1000"
        gif:gif_src="@drawable/animated_gif" />

    <TextView
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/gif_view"
        android:text="暂停" />

</RelativeLayout>

与使用普通的View一样,将需要的资源传入即可.

时间: 2024-10-19 00:07:28

android自定义GifView显示gif动画的相关文章

Android 自定义 ListView 显示网络歌曲列表

本文内容 环境 项目结构 演示自定义 ListView 显示网络歌曲列表 参考资料 本文最开始看的一个国人的文章,没有源代码,根据文中提供的源代码,自己新建的项目(最可气的是,没有图标图片资源,只能自己乱编),但程序不是很稳定,有时能显示出列表中的缩略图,有时显示不出来,还在主线程访问了网络.后看文章评论,作者给出英文原文链接,本来想这下没事了吧,结果下载源代码运行后,还是有问题~仔细看英文原文,原来他也是根据 Github 上一个项目的基础上搞的,只是添加了式样,以及显示完整的歌曲列表,包括歌

Android自定义下拉刷新动画--仿百度外卖下拉刷新

好久没写博客了,小编之前一段时间一直在找工作,从天津来到了我们的大帝都,感觉还不错.好了废话不多说了,开始我们今天的主题吧.现如今的APP各式各样,同样也带来了各种需求,一个下拉刷新都能玩出花样了,前两天订饭的时候不经意间看到了"百度外卖"的下拉刷新,今天的主题就是它–自定义下拉刷新动画. 看一下实现效果吧: 动画 我们先来看看Android中的动画吧: Android中的动画分为三种: Tween动画,这一类的动画提供了旋转.平移.缩放等效果. Alpha – 淡入淡出 Scale

android 自定义Toast显示风格

1.创建一个自己想要显示Toast风格的XML如下代码(toast_xml.xml): [html] view plaincopyprint? <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match

Android—基于GifView显示gif动态图片

android中显示gif动态图片用到了开源框架GifView 1.拷GifView.jar到自己的项目中. 2.将自己的gif图片拷贝到drawable文件夹 3.在xml文件中设置基本属性: <com.ant.liao.GifView android:id="@+id/gifView" android:layout_centerInParent="true" android:layout_width="wrap_content" and

android布局中显示隐藏动画

android 在布局中提供属性,能简单的添加动画效果,如下: <LinearLayout ... animateLayoutChanges="true" ... /> 当对布局中的view添加删除,隐藏或显示, 都会有一个淡入淡出,和位移动画. 除了在XML布局文件中使用animateLayoutChanges 属性.也可以创建 LayoutTransition 对象通过 setLayoutTransition() 方法设置进去.源码如下: private ViewGro

Android 自定义录音、播放动画View,让你的录音浪起来

最近公司项目有一个录音的录制和播放动画需求,然后时间是那么紧,那么赶紧开撸. 先看效果图 嗯,然后大致就是这样,按住录音,然后有一个倒计时,最外层一个进度条,还有一个类似模拟声波的动画效果(其实中间的波浪会根据声音的大小浪起来的~) 2 实现思路 然后,我们适当的来分析一下这个录音动画的实现方式.这个肯定是通过自定义控件,咱们来把这个效果完完全全画出来. 大致包括以下几个点: 1. 最外层的进度条,最坑的就是一开始的一个渐变的效果 2. 然后进度条最前方是有一个点的(我肯定选择用图片来实现) 3

android自定义SurfaceView实现跑男动画

先看效果: 代码实现: import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import andr

Android 自定义 ListView 上下拉动&ldquo;刷新最新&rdquo;和&ldquo;加载更多&rdquo;歌曲列表

本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码太多,点击此处下载,自己调试一下. 下载 Demo 环境 Windows 2008 R2 64 位 Eclipse ADT V22.6.2,Android 4.4.3 SAMSUNG GT-I9008L,Android OS 2.2.2 测试数据 本演示的歌曲信息,共有 20 条,包括歌手名.歌曲名.时长.缩

Android显示GIF动画 GifView

android中显示gif动画原生态一般支持的不是很好,故找了一个开源的项目,现简单介绍如下: GifView 是一个为了解决android中现在没有直接显示gif的view,只能通过mediaplay来显示这个问题的项目,其用法和 ImageView一样,支持gif图片问题:估计会出现OOM的问题,请大家思考如何避免OOM. 使用方法: 1-把GifView.jar加入你的项目. 2-在xml中配置GifView的基本属性,GifView继承自View类,和Button.ImageView一样