GIF在Windows上是常见的图片格式,主要用来播放短小的动画。但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来的只是该gif文件的第一帧图片。

对于这种情况,Android带来了帧动画技术,通过连续播放每帧图片,从而实现帧动画的效果。不过若要使用帧动画,我们得自己准备好若干帧,然后把这些图片帧编入图片队列,这样才可以显示动画。对于如何从gif文件中提取出每帧图片,博主在之前的文章中有做了说明,详见《 Android开发笔记(十)常用的图片加工操作》。

可是手工分解gif文件也太麻烦了,如果gif数量多的话,岂不累坏了。能否通过代码直接从gif文件中提取每帧图片呢?答案是有的,已经有大牛研究出来了,那么我们直接把相关算法拿过来,改改就可以用了。下面是调用的代码例子,为方便比较帧动画和GIF动画的效果,代码同时实现了两种动画

import java.io.InputStream;import com.example.exmgif.util.GifImage;
import com.example.exmgif.util.GifImage.GifFrame;import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener {private ImageView iv_gif;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn_play1 = (Button) findViewById(R.id.btn_play1);Button btn_play2 = (Button) findViewById(R.id.btn_play2);btn_play1.setOnClickListener(this);btn_play2.setOnClickListener(this);iv_gif = (ImageView) findViewById(R.id.iv_gif);}private Drawable getDraw(int id) {return getResources().getDrawable(id);}private void showFrameAnimation() {//帧动画需要把每帧图片加入AnimationDrawable队列AnimationDrawable animationList = new AnimationDrawable();animationList.addFrame(getDraw(R.drawable.flow_p1), 50);animationList.addFrame(getDraw(R.drawable.flow_p2), 50);animationList.addFrame(getDraw(R.drawable.flow_p3), 50);animationList.addFrame(getDraw(R.drawable.flow_p4), 50);animationList.addFrame(getDraw(R.drawable.flow_p5), 50);animationList.addFrame(getDraw(R.drawable.flow_p6), 50);animationList.addFrame(getDraw(R.drawable.flow_p7), 50);animationList.addFrame(getDraw(R.drawable.flow_p8), 50);//setOneShot为true表示只播放一次,为false表示循环播放animationList.setOneShot(false);iv_gif.setImageDrawable(animationList);animationList.start();}private void showGifAnimation(int resid) {InputStream is = getResources().openRawResource(resid);GifImage gifImage = new GifImage();int code = gifImage.read(is);if (code == GifImage.STATUS_OK) {  GifFrame[] frameList = gifImage.getFrames();AnimationDrawable gifList = new AnimationDrawable();for (int i=0; i<frameList.length; i++) {//BitmapDrawable用于把Bitmap格式转换为Drawable格式BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), frameList[i].image);gifList.addFrame(bitmapDrawable, frameList[i].delay);}gifList.setOneShot(false);iv_gif.setImageDrawable(gifList);gifList.start();} else if (code == GifImage.STATUS_FORMAT_ERROR) {Toast.makeText(this, "该图片不是gif格式", Toast.LENGTH_LONG).show();} else {Toast.makeText(this, "gif图片读取失败:"+code, Toast.LENGTH_LONG).show();}}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_play1) {showFrameAnimation();} else if (v.getId() == R.id.btn_play2) {showGifAnimation(R.drawable.welcome);}}}

可以看到帧动画并非补间动画那样有专门的Animation类,而是通过AnimationDrawable来实现(又是Drawable)。另外,代码在从gif文件抽取每帧图片时,用到了BitmapDrawable,该类可把Bitmap格式转换为Drawable格式。不知不觉,我们已经应用了十几个Drawable中的大半,它们分别是:
1、StateListDrawable:详见《 Android开发笔记(七)初识Drawable》
2、ShapeDrawable:详见《 Android开发笔记(八)神奇的shape》
3、NinePatchDrawable:详见《 Android开发笔记(九)特别的.9图片》
4、TransitionDrawable:详见《 Android开发笔记(十五)淡入淡出动画》
5、AnimationDrawable:见本文《 Android开发笔记(十七)GIF动画的实现》
6、BitmapDrawable:见本文《 Android开发笔记(十七)GIF动画的实现》
7、GradientDrawable:详见《 Android开发笔记(十八)书籍翻页动画》

下面是GIF动画和帧动画的效果图

点击下载本文用到的GIF动画和帧动画的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(十七)GIF动画的实现GifAnimation相关推荐

  1. android开发笔记之属性动画

    属性动画简单介绍 作用对象:任意 Java 对象 不再局限于 视图View对象 实现的动画效果:可自定义各种动画效果 不再局限于4种基本变换:平移.旋转.缩放 & 透明度 特点 作用对象进行了 ...

  2. Android开发笔记(一百五十七)使用OpenGL实现翻书动画

    上一篇文章介绍了如何通过纹理渲染绘制地球仪,当然OpenGL的三维图形处理能力是很强大的,只要善于利用OpenGL,就能很方便地虚拟各种现实生活中的动画效果.本文再来谈谈使用OpenGL实现浏览电子书 ...

  3. Android开发笔记(一百八十七)利用估值器实现弹幕动画

    如今上网看电影电视越发流行了,追剧的时候经常看到视频上方数行评论向左边飘去,犹如子弹那样飞快掠过,这些评论文字因此得名"弹幕".弹幕评论由正在观看的网友们即兴发表,故而连绵不绝从画 ...

  4. Android开发笔记(一百四十五)仿应用宝的垃圾清理动画

    除了动画监听器,动画组合也是各类动画常见的用法,比如把几个补间动画组合起来,就形成了集合动画AnimationSet:把几个属性动画组合起来,就形成了属性动画组合AnimatorSet.那么能否把几个 ...

  5. Android开发笔记(一百四十四)高仿支付宝的头部伸缩动画

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想 ...

  6. Android开发笔记(一百三十七)自定义行为Behavior

    协调布局CoordinatorLayout能够让内部的子控件互相配合着移动,这跟以往孤立的控件运动截然不同,协调运动的结果,意味着App画面更加流畅.自然,也更符合日常生活中的动作场景.如果你对Coo ...

  7. Android开发笔记(一百三十二)矢量图形与矢量动画

    矢量图形VectorDrawable 与水波图形RippleDrawable一样,矢量图形VectorDrawable也是Android5.0之后新增的图形类.矢量图不同于一般的图形,它是由一系列几何 ...

  8. Android开发笔记(一百三十一)水波图形与水波动画

    水波图形RippleDrawable RippleDrawable是Android在5.0之后新增的图形类,它的作用是在点击时展示水波动画,从而提示用户在这里按压了屏幕.这个提示效果类似于状态图形St ...

  9. Android开发笔记(一百一十七)app省电方略

    电源管理PowerManager PowerManager是Android的电源管理类,用于管理电源操作如睡眠.唤醒.重启以及调节屏幕亮度等等. PowerManager的对象从系统服务POWER_S ...

最新文章

  1. jetty的Form too large异常解决方案
  2. Making the impossible: 3 nodes intercontinental replication--转载
  3. Mysql多表查询(案例1)
  4. 男士美容,这些方面你做了没? - 生活至上,美容至尚!
  5. 计算机科学与技术 net,计算机科学与技术
  6. 国内 UOS 统一操作系统曝光;联想宣布要 All in 5G​;Android Studio 新版发布 | 极客头条...
  7. ES6新语法之let关键字;有别于传统关键字var的使用
  8. 5-21 求前缀表达式的值(25分)
  9. ios tabtar 使用方法_Appium界面自动化测试(13)(iOS/Python):元素定位及操作
  10. 什么是python元祖_python元组
  11. 电子工程师的自我修养 - 恒流源电路分析
  12. regeneratorRuntime is not defined
  13. adb shell error: device offline
  14. 27个常用stata命令(2)
  15. 焊接机器人比传统手工焊接有哪些优势
  16. python接外包项目_微信外包项目,接口开发流程小记
  17. nyoj 3 多边形重心问题
  18. 《只是为了好玩:Linux之父林纳斯自传》
  19. 计算机基础:今天一次把 Unicode 和 UTF-8 说清楚
  20. wireshark抓包vx ip

热门文章

  1. ROS入门-5.认识ROS及ROS的基本概念
  2. 机器学习实战(一)k-近邻kNN(k-Nearest Neighbor)
  3. eyoucms内容添加发布
  4. 浮动和清除(闭合)浮动
  5. 第十二:Pytest进阶之配置文件
  6. android系统 wifi,Android系统wifi分析-手动连接过程
  7. 若依框架在未登录的情况下访问swagger页面
  8. Soul网关源码阅读(七)限流插件初探
  9. substr判断最后一个是不是逗号_考研最后一个月是不是很累?
  10. opc客户端_OPC UA 预备知识 OPC 核心概念