方案一、开源项目android-gif-drawable

特点:

1、底层使用到jni ,不易出现oom

2、调用方便

android开源库android-gif-drawable的使用

android的开源库是用来在android上显示gif图片的。我在网上查了一下,大家说这个框架写的不错,加载大的gif图片   不会内存溢出,于是我就想试试这个开源库,我下了作者的源代码和例子,但是我却跑不起来。不知道为什么,我又到网上去找使用这个开源库的例子发现有一个,我也下载了下来,发现还是跑不起来。我决定自己好好试试这个源代码,终于在我的努力下现在可以用了。废话完了 现在教大家怎么用这个库。

详情见:http://my.oschina.net/u/1175746/blog/288258

我自己的demo例子,是一只飞行的小鸟,下载地址:http://download.csdn.net/detail/nnmmbb/8077225

方案二、通过工具打散gif成一张张的图片,


然后播放帧动画


特点:1、可以控制一次播放或无限次循环播放

2、可以点击播放或自动播放

 Android 播放Gif 动画

2010-09-06 22:16:04

标签:移动开发 播放 动画 Gif Android
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://terryblog.blog.51cto.com/1764499/388226

在Android 中是不支持直接使用Gif 图片关联播放帧动画,如下动画在Android 中是无法播放的:

Android 提供了另外一种解决的办法,就是使用AnimationDrawable 这一函数使其支持逐帧播放,但是如何把gif 图片打散开来,成为每一帧的图片呢?下面介绍两种比较不错的软件,可以帮我们打散图片。

gifsplitter2.0

下载地址:gif分割

使用方法如下:

这一软件分割图片都是bmp图片,图片比较大,这里不推荐使用,尽量节省不必要的字节,所以这里推荐使用如下 软件

easygifanimator

软件下载:动画分割器

使用方法如下:

点击文件将帧文件导出即可

得到了帧文件后我们可以就编写代码,在res目录下新建anim动画文件夹,写下如下代码

<?xml version="1.0" encoding="UTF-8"?>
<animation-list android:oneshot="false"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:duration="150" android:drawable="@drawable/xiu0" />
    <item android:duration="150" android:drawable="@drawable/xiu1" />
    <item android:duration="150" android:drawable="@drawable/xiu2" />
    <item android:duration="150" android:drawable="@drawable/xiu3" />
</animation-list> 

对应的item 为顺序的图片从开始到结束,duration为每张逐帧播放间隔,oneshot 为false 代表循环播放,设置为true 即播放一次即停止。

对应Activity 代码如下编写:


import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;

public class animActivity extends Activity implements OnClickListener {
    ImageView iv = null;

/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

iv = (ImageView) findViewById(R.id.ImageView01);
        iv.setOnClickListener(this);
    }

@Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        AnimationDrawable anim = null;
        Object ob = iv.getBackground();
        anim = (AnimationDrawable) ob;
        anim.stop();
        anim.start();
    }
}

使用AnimationDrawable 对象获得图片的图片,然后指定这个AnimationDrawable 开始播放动画

Tip:使用此方法不会默认播放,必须要有事件触发才可播放动画,如上面的通过点击监听触发动画的播放

那么如何使用图片自动播放呢?我们可以联想一下,ProgressBar 是不是默认的时候就会转,那就是那个圆形的进度条,是的。我们可以对它进行改造合它也可以自动播放,在Values 文件下新建一个styles 文件,编写如下代码 :

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <style name="animStyle" parent="@android:style/Widget.ProgressBar.Large">
        <item name="android:indeterminateDrawable">@anim/test</item>
    </style>
</resources> 

上面样式文件自Widget.ProgressBar.Large 为其设置动画文件,我们在XML中就可以通过设置它的样式使其为我们工作

    <ProgressBar android:id="@+id/ProgressBar01" style="@style/animStyle"
        android:layout_width="128px" android:layout_height="128px"></ProgressBar>

OK,就是这么简单,下面看看运行效果:

本文出自 “Terry_龙” 博客,请务必保留此出处http://terryblog.blog.51cto.com/1764499/388226


方案三、 PowerImageView

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100315

我个人是比较喜欢逛贴吧的,贴吧里总是会有很多搞笑的动态图片,经常看一看就会感觉欢乐很多,可以释放掉不少平时的压力。确实,比起一张单调的图片,动态图片明显更加的有意思。一般动态图片都是GIF格式的,浏览器中可以直接将这种格式的图片播放成动画。

不过很可惜的是,Android的原生控件并不支持播放GIF格式的图片。我们都知道,在Android中如果想要显示一张图片,可以借助ImageView控件来完成,但是如果将一张GIF图片设置到ImageView里,它只会显示这张图片的第一帧,不会产生任何的动画效果。

那么就没有办法在Android里播放GIF图片了吗?当然不是,我们可以通过自定义控件的方式来实现这个功能。ImageView无法播放GIF图片说明它的功能还不够强大,那么今天我们就来编写一个PowerImageView控件,让它既能支持ImageView控件原生的所有功能,同时还可以播放GIF图片。

下面我们就开始吧,首先新建一个项目,起名就叫PowerImageViewTest,这里使用Android 4.0的API。

由于是要自定义控件,我们还可能会用到一些自定义的属性,因此在values目录下新建一个attrs.xml的文件,可以在这个文件中添加任何需要自定义的属性。这里我们目前只需要一个auto_play属性,代码如下所示:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="PowerImageView">
  4. <attr name="auto_play" format="boolean"></attr>
  5. </declare-styleable>
  6. </resources>

完成了这个文件之后,下面我们来开始编写最最重要的PowerImageView类,由于这个类要支持ImageView的所有功能,因此需要让PowerImageView继承自ImageView,代码如下所示:

[java] view plaincopy
  1. public class PowerImageView extends ImageView implements OnClickListener {
  2. /**
  3. * 播放GIF动画的关键类
  4. */
  5. private Movie mMovie;
  6. /**
  7. * 开始播放按钮图片
  8. */
  9. private Bitmap mStartButton;
  10. /**
  11. * 记录动画开始的时间
  12. */
  13. private long mMovieStart;
  14. /**
  15. * GIF图片的宽度
  16. */
  17. private int mImageWidth;
  18. /**
  19. * GIF图片的高度
  20. */
  21. private int mImageHeight;
  22. /**
  23. * 图片是否正在播放
  24. */
  25. private boolean isPlaying;
  26. /**
  27. * 是否允许自动播放
  28. */
  29. private boolean isAutoPlay;
  30. /**
  31. * PowerImageView构造函数。
  32. *
  33. * @param context
  34. */
  35. public PowerImageView(Context context) {
  36. super(context);
  37. }
  38. /**
  39. * PowerImageView构造函数。
  40. *
  41. * @param context
  42. */
  43. public PowerImageView(Context context, AttributeSet attrs) {
  44. this(context, attrs, 0);
  45. }
  46. /**
  47. * PowerImageView构造函数,在这里完成所有必要的初始化操作。
  48. *
  49. * @param context
  50. */
  51. public PowerImageView(Context context, AttributeSet attrs, int defStyle) {
  52. super(context, attrs, defStyle);
  53. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PowerImageView);
  54. int resourceId = getResourceId(a, context, attrs);
  55. if (resourceId != 0) {
  56. // 当资源id不等于0时,就去获取该资源的流
  57. InputStream is = getResources().openRawResource(resourceId);
  58. // 使用Movie类对流进行解码
  59. mMovie = Movie.decodeStream(is);
  60. if (mMovie != null) {
  61. // 如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
  62. isAutoPlay = a.getBoolean(R.styleable.PowerImageView_auto_play, false);
  63. Bitmap bitmap = BitmapFactory.decodeStream(is);
  64. mImageWidth = bitmap.getWidth();
  65. mImageHeight = bitmap.getHeight();
  66. bitmap.recycle();
  67. if (!isAutoPlay) {
  68. // 当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
  69. mStartButton = BitmapFactory.decodeResource(getResources(),
  70. R.drawable.start_play);
  71. setOnClickListener(this);
  72. }
  73. }
  74. }
  75. }
  76. @Override
  77. public void onClick(View v) {
  78. if (v.getId() == getId()) {
  79. // 当用户点击图片时,开始播放GIF动画
  80. isPlaying = true;
  81. invalidate();
  82. }
  83. }
  84. @Override
  85. protected void onDraw(Canvas canvas) {
  86. if (mMovie == null) {
  87. // mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
  88. super.onDraw(canvas);
  89. } else {
  90. // mMovie不等于null,说明是张GIF图片
  91. if (isAutoPlay) {
  92. // 如果允许自动播放,就调用playMovie()方法播放GIF动画
  93. playMovie(canvas);
  94. invalidate();
  95. } else {
  96. // 不允许自动播放时,判断当前图片是否正在播放
  97. if (isPlaying) {
  98. // 正在播放就继续调用playMovie()方法,一直到动画播放结束为止
  99. if (playMovie(canvas)) {
  100. isPlaying = false;
  101. }
  102. invalidate();
  103. } else {
  104. // 还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮
  105. mMovie.setTime(0);
  106. mMovie.draw(canvas, 0, 0);
  107. int offsetW = (mImageWidth - mStartButton.getWidth()) / 2;
  108. int offsetH = (mImageHeight - mStartButton.getHeight()) / 2;
  109. canvas.drawBitmap(mStartButton, offsetW, offsetH, null);
  110. }
  111. }
  112. }
  113. }
  114. @Override
  115. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  116. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  117. if (mMovie != null) {
  118. // 如果是GIF图片则重写设定PowerImageView的大小
  119. setMeasuredDimension(mImageWidth, mImageHeight);
  120. }
  121. }
  122. /**
  123. * 开始播放GIF动画,播放完成返回true,未完成返回false。
  124. *
  125. * @param canvas
  126. * @return 播放完成返回true,未完成返回false。
  127. */
  128. private boolean playMovie(Canvas canvas) {
  129. long now = SystemClock.uptimeMillis();
  130. if (mMovieStart == 0) {
  131. mMovieStart = now;
  132. }
  133. int duration = mMovie.duration();
  134. if (duration == 0) {
  135. duration = 1000;
  136. }
  137. int relTime = (int) ((now - mMovieStart) % duration);
  138. mMovie.setTime(relTime);
  139. mMovie.draw(canvas, 0, 0);
  140. if ((now - mMovieStart) >= duration) {
  141. mMovieStart = 0;
  142. return true;
  143. }
  144. return false;
  145. }
  146. /**
  147. * 通过Java反射,获取到src指定图片资源所对应的id。
  148. *
  149. * @param a
  150. * @param context
  151. * @param attrs
  152. * @return 返回布局文件中指定图片资源所对应的id,没有指定任何图片资源就返回0。
  153. */
  154. private int getResourceId(TypedArray a, Context context, AttributeSet attrs) {
  155. try {
  156. Field field = TypedArray.class.getDeclaredField("src");
  157. field.setAccessible(true);
  158. TypedValue typedValueObject = (TypedValue) field.get(a);
  159. return typedValueObject.resourceId;
  160. } catch (Exception e) {
  161. e.printStackTrace();
  162. } finally {
  163. if (a != null) {
  164. a.recycle();
  165. }
  166. }
  167. return 0;
  168. }
  169. }

这个类的代码注释已经非常详细了,我再来简单地解释一下。可以看到,我们重写了ImageView中所有的构建函数,使得PowerImageView的用法可以和ImageView完全相同。在构造函数中,则是对所有必要的数据进行了初始化操作。首先,我们调用了getResourceId()方法去获取图片资源对应的id值,在getResourceId()方法内部是通过Java的反射机制来进行获取的。得到了图片资源的id后,我们将它转换成InputStream,然后传入到Movie.decodeStream()方法中以解码出Movie对象。如果得到的Movie对象等于null,说明这是一张普通的图片资源,就不再进行任何特殊处理,因为父类ImageView都帮我们处理好了。如果得到的Movie对象不等于null,则说明这是一张GIF图片,接着就要去获取是否允许自动播放、图片的宽高等属性的值。如果不允许自动播放,还要给播放按钮注册点击事件,默认是不允许自动播放的。

接下来会进入到onMeasure()方法中。在这个方法中我们进行判断,如果这是一张GIF图片,则需要将PowerImageView的宽高重定义,使得控件的大小刚好可以放得下这张GIF图片。

再往后就会进入到onDraw()方法中。在这个方法里同样先判断当前是一张普通的图片还是GIF图片,如果是普通的图片就直接调用super.onDraw()方法交给ImageView去处理就好了。如果是GIF图片,则先判断该图是否允许自动播放,允许的话就调用playMovie()方法去播放GIF图片就好,不允许的话则会先在PowerImageView中绘制该GIF图片的第一帧,并在图片上绘制一个播放按钮,当用户点击了播放按钮时,再去调用playMovie()方法去播放GIF图片。

下面我们来看看playMovie()方法中是怎样播放GIF图片的吧。可以看到,首先会对动画开始的时间做下记录,然后对动画持续的时间做下记录,接着使用当前的时间减去动画开始的时间,得到的时间就是此时PowerImageView应该显示的那一帧,然后借助Movie对象将这一帧绘制到屏幕上即可。之后每次调用playMovie()方法都会绘制一帧图片,连贯起来也就形成了GIF动画。注意,这个方法是有返回值的,如果当前时间减去动画开始时间大于了动画持续时间,那就说明动画播放完成了,返回true,否则返回false。

完成了PowerImageView的编写,下面我们就来看一看如何使用它吧,其实非常简单,打开或新建activity_main.xml,代码如下所示:

[html] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent" >
  4. <com.example.powerimageviewtest.PowerImageView
  5. android:id="@+id/image_view"
  6. android:layout_width="wrap_content"
  7. android:layout_height="wrap_content"
  8. android:layout_centerInParent="true"
  9. android:src="@drawable/anim"
  10. />
  11. </RelativeLayout>

可以看到,PowerImageView的用法和ImageView几乎完全一样,使用android:src属性来指定一张图片即可,这里指定的anim就是一张GIF图片。然后我们让PowerImageView在布局里居中显示。

MainActivity中的代码都是自动生成的,这里就不再贴出来了。在AndroidManifest.xml中还有一点需要注意,有些4.0以上系统的手机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁用硬件加速功能,可以通过指定android:hardwareAccelerated属性来完成,代码如下所示:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.powerimageviewtest"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6. <uses-sdk
  7. android:minSdkVersion="14"
  8. android:targetSdkVersion="17" />
  9. <application
  10. android:allowBackup="true"
  11. android:icon="@drawable/ic_launcher"
  12. android:label="@string/app_name"
  13. android:theme="@style/AppTheme"
  14. android:hardwareAccelerated="false"
  15. >
  16. <activity
  17. android:name="com.example.powerimageviewtest.MainActivity"
  18. android:label="@string/app_name" >
  19. <intent-filter>
  20. <action android:name="android.intent.action.MAIN" />
  21. <category android:name="android.intent.category.LAUNCHER" />
  22. </intent-filter>
  23. </activity>
  24. </application>
  25. </manifest>

现在可以来运行一下代码了,一打开程序你就会看到GIF图片的第一帧,点击图片之后就可以播放GIF动画了,如下图所示:

然后我们还可以通过修改activity_main.xml中的代码,给它加上允许自动播放的属性,代码如下所示:

[html] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:attr="http://schemas.android.com/apk/res/com.example.powerimageviewtest"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <com.example.powerimageviewtest.PowerImageView
  6. android:id="@+id/image_view"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_centerInParent="true"
  10. android:src="@drawable/anim"
  11. attr:auto_play="true"
  12. />
  13. </RelativeLayout>

这里使用了刚才我们自定义的属性,通过attr:auto_play来启用和禁用自动播放功能。现在将auto_play属性指定成true后,PowerImageView上就不会再显示一个播放按钮,而是会循环地自动播放动画。现在重新运行一下程序,效果如下图所示:

怎么样?效果还不错吧。不仅如此,PowerImageView还继承了ImageView原生的所有功能,只要指定的不是GIF图片,PowerImageView表现的结果就和ImageView完全一致,让我们来放一张普通的PNG图片看看吧,修改activity_main.xml中的代码,如下所示:

[html] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent" >
  4. <com.example.powerimageviewtest.PowerImageView
  5. android:id="@+id/image_view"
  6. android:layout_width="wrap_content"
  7. android:layout_height="wrap_content"
  8. android:layout_centerInParent="true"
  9. android:src="@drawable/conan"
  10. />
  11. </RelativeLayout>

这里在src属性里面指定了一张名字为conan的图片,这是一张PNG图片,效果如下图所示:

一张图片在布局正中央显示出来了,正是普通ImageView所具备的功能。你还可以在PowerImageView中指定android:scaleType等属性,用法和原生的ImageView完全一样。怎么样,是不是确实算得上是Power版的ImageView了?

好了,今天的讲解到此结束,有疑问的朋友请在下面留言。

源码下载,请点击这里

android 播放gif方案集合相关推荐

  1. android的快速开发框架集合

    android的快速开发框架集合 出自:http://blog.csdn.net/shulianghan/article/details/18046021 1.Afinal  (快速开发框架) 简介: ...

  2. Android开源框架【集合】

    Android开源框架[集合] 图解一览 Square& JakeWharton 框架名称 功能描述 Picasso 一个强大的图片下载与缓存的库 OkHttp Square出品,一个Http ...

  3. android系列:第一篇 android开发常用命令集合,代码目录简介

    下面整理了android开发常用命令集合如adb命令,adb over wifi,jgrep等代码搜索命令,编译环境变量配置,lunch平台选择,mm模块编译,godir代码路径跳转,log.v()等 ...

  4. Android 热修复方案Tinker(五) SO补丁加载

    基于Tinker V1.7.5 Android 热修复方案Tinker(一) Application改造 Android 热修复方案Tinker(二) 补丁加载流程 Android 热修复方案Tink ...

  5. 一种解决h5页面背景音乐不能自动播放的方案

    一种解决h5页面背景音乐不能自动播放的方案 场景:微信.浏览器.App 普通解决方案:采用audio标签的autoplay属性 现象: 1.大部分IOS系统和少部分Android微信不支持自动播放 解 ...

  6. Android播放网络视频截图

    Android播放网络视频截图 最近博主遇到一个Android电视的开发项目,项目需要电视客户端播放服务器端视频,通过遥控器一键截图,并将截图云推送到手机客户端,于是博主就开始找度神去求助了,毕竟以前 ...

  7. Android 换肤方案详解(一)

    引言 在我们的开发中,也许有些项目会有换肤的需求,这个时候会比较头疼怎么做才能做到一键换肤呢?大家肯定是希望只要一行代码就能调用最好.下面我们先分析一下换肤的本质是什么? 原理 换肤,其本质无非就是更 ...

  8. Android投屏方案(基于cling)

    一 .前言 最近做了一个浏览器&视频播放的项目,是在73.0.3683.90版本的chrome源码上修改而来,涉及到抓取网页里视频的播放地址.播放视频.视频投屏.视频下载.网页内广告屏蔽等方面 ...

  9. 全面盘点当前Android后台保活方案的真实运行效果(截止2019年前)

    全面盘点当前Android后台保活方案的真实运行效果(截止2019年前) 本文原作者"minminaya",作者网站:minminaya.cn,为了提升文章品质,即时通讯网对内容作 ...

  10. Android应用优化方案四

    Android应用优化方案一 点击进入 Android应用优化方案二 点击进入 Android应用优化方案三 点击进入 Android应用优化方案四 在Java中,内存的分配是由程序完成的,而内存的释 ...

最新文章

  1. WINDOWS SERVER 2003从入门到精通之“域控制器安全策略”打开错误的解决方法
  2. python绘制简单直方图-Python数据分析:统计函数绘制简单图形
  3. Outlook新邮件要双击打开后才显示为已读
  4. 微软推出 Microsoft.Data.SqlClient,替代 System.Data.SqlClient
  5. 判断unsigned long long乘法溢出_信息安全课程17:缓冲区溢出2
  6. 微信小程序开发学习笔记006--微信小程序组件详解02
  7. casio计算器计算统计数据
  8. C文件编译、链接指令
  9. python调用按键精灵插件_按键精灵 插件命令 重中之重务必要记住怎么操作
  10. 内网IM软件推荐:10分钟快速搭建,支持局域网私有化部署
  11. 美国计算机游戏设计大学排名,USNews美国大学游戏设计专业排名
  12. python中re模块的group()和groups()
  13. Tomcat下载安装及配置Https教程
  14. 北航2019计算机学院就业报告,北京航空航天大学2019届毕业生就业质量年度报告.pdf...
  15. 最新炫酷恶趣图制作神器小程序源码+支持流量主/功能强大
  16. 线程2--主线程(main线程)
  17. 【玩转CSS】盒子模型
  18. 写运维实习生第五周实习周报,包括心得体会和下周计划,多于300字
  19. 阿里云免费SSL证书申请与安装使用-附Nginx,Apache,IIS 6,IIS 8配置SSL教程
  20. 制作人 Joe Carrell 教你充分释放TB12音色野兽

热门文章

  1. 世界时、国际原子时、协调世界时到底有什么联系(最简单易懂版)
  2. 戴尔-卡耐基:《人性的弱点 How to Win Friends And Influence People》总结
  3. 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
  4. SAP ABAP APO计划订单生产日期调整
  5. [机缘参悟-64]:《兵者,诡道也》-5-三十六计解读-混战计
  6. 制作“玄”字logo
  7. 【MATLAB笔记】对矩阵进行满秩分解
  8. Swagger界面丑、功能弱怎么破?用Postman增强下就给力了!
  9. 让微积分穿梭于工作与学习之间(23):用极限的思想把一元一次方程和一元二次方程的根式解统一起来
  10. 点阵发光管怎么用C语言编程,LED点阵经验各种点阵驱动方法讲解