Android实现可播放GIF动画的ImageView_Android

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

1.自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="GifImageView">
  <attr name="auto_play" format="boolean"></attr>
 </declare-styleable>
</resources>

 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来完成。

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

现在我们来看看运行后效果如何吧,
布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 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" >

 <com.hx.gifimageview.GifImageView
  android:layout_width="150dip"
  android:layout_height="150dip"
  android:layout_margin="10dp"
  android:src="@drawable/shulan"
  attr:auto_play="false" />

 <com.hx.gifimageview.GifImageView
  android:layout_width="150dip"
  android:layout_height="150dip"
  android:layout_margin="10dp"
  android:src="@drawable/shulan"
  attr:auto_play="true" />

 <com.hx.gifimageview.GifImageView
  android:layout_width="150dip"
  android:layout_height="150dip"
  android:layout_margin="10dp"
  android:src="@drawable/jingtai"
  attr:auto_play="true" />
</LinearLayout>

 

图一的auto_play属性为false,会显示第一帧和一个播放按钮,点击后Gif图片会自动运行。
图二的auto_play属性为true,会自动循环播放Gif。
图三我们给的资源是静态图片,因为自定义View继承ImageView,所以具备ImageView所有特性,因此也能显示静态图片。

源码下载:http://xiazai.jb51.net/201609/yuanma/GifImageView(jb51.net).rar

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索gif动画
gifimageview、imageview gif、gifimageview用法、android gifimageview、imageview加载gif图片,以便于您获取更多的相关知识。

时间: 2024-11-08 19:47:02

Android实现可播放GIF动画的ImageView_Android的相关文章

Android自定义View播放Gif动画的示例

前言 GIF是一种很常见的动态图片格式,在Android中它的使用场景非常多,大到启动页动画.小到一个Loading展示,都可以用GIF动画来完成,使用也很方便,直接从美工那边拿过来用就成.如果项目赶时间或者自定义原生动画太麻烦,GIF都是一个很好的选择,相比于最新的WEBP格式的动画,也有更好的兼容性(毕竟已经出现很多年了). 关于图片加载我一直用的是Google推荐的 Glide ,图片加载和缓存都做的很好,同样也支持GIF动画.不过Glide默认就是循环播放Gif,没有开放相关的接口来控制

Android播放gif动画,增加屏幕掉金币效果

前言:播放gif的版本有很多,我这边使用Android自带的Movie类播放gif动画,也是在别人的基础上进行修改.有同样需求的朋友可以参考我的demo. 1.效果图如下:    2.部分主要代码 MainActivity.java  给封装的GifView设置背景gif图片资源, 绘制金币,同时开启金币屏幕掉下来的效果,监听gif播放完毕动画,结束掉金币的动画   public class MainActivity extends Activity implements OnClickList

Android高级控件(二)——SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现

Android高级控件(二)--SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现 写这个的原因呢,也是因为项目中用到了gif动画,虽然网上有很多的架包可以实现,不过我们还是要追究一下原理怎么做的,我们新建一个GifLibrary,然后右键Properties--Android,我们把架包勾上 然后我们新建一个类GifSurfaceView继承自SurfaceView并且实现它的Callback接口 GifSurfaceView package com.lgl.gif

Android中播放Gif动画取巧的办法_Android

由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那android 的 WebView 也能播放,写了个Demo,果然能播放. 1.将gif的文件放到android的资源文件夹里面 2.写个html,将android的gif源放到WebView里面去加载 <RelativeLayout xmlns:android="http://schemas.a

Android中播放Gif动画取巧的办法

由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那android 的 WebView 也能播放,写了个Demo,果然能播放. 1.将gif的文件放到android的资源文件夹里面 2.写个html,将android的gif源放到WebView里面去加载 <RelativeLayout xmlns:android="http://schemas.a

android 界面跳转和动画同时运行是出现的问题。

问题描述 android 界面跳转和动画同时运行是出现的问题. 我想做的是,打开一个客户端(安卓平台),然后显示一段动画,动画结束之后就跳转到另外一个界面.但是,这两个功能单个实现的时候都没有问题,两个一起运行是就出问题了,编译通过,然后启动程序,开始演示动画,当动画演示完毕,准备跳转界面的时候,程序就出问题了,就是直接退出了.代码如下. public class Open extends Activity{ private ImageView imageView; private Animat

android视频解码-android视频加速播放可选择多少倍速播放

问题描述 android视频加速播放可选择多少倍速播放 请问android视频加速播放是如何实现的!例如以1.5倍速播放视频.求教原理 解决方案 视频是由连续的帧形成的,一个帧对应一个画面,就像胶片电影.通过每秒切换多少帧形成连续的画面,当切换速度大于眼睛所能接受的速度时(貌似人眼每秒能接受24帧),那么我们就无法察觉这些变化了,我们大脑所接受的图像便是一段视频图像.这便是帧率.假如一个视频的默认帧率为60帧每秒,当我们在播放时采用120帧每秒的帧速率.那么我们看到的视频就以原来的2倍速度播放.

Android基础知识之frame动画效果_Android

上一篇我们说了Android中的tween动画,这一篇我们说说frame动画,frame动画主要是实现了一种类似于gif动画的效果,就是多张图按预先设定好的时间依次连续显示. 新建一个android项目,名字叫做frameTest,在res文件夹下新建一个文件夹叫做anim,我们的frame动画的xml文件就放在这里. 在anim中新建一个frame.xml文件,内容如下: <?xml version="1.0" encoding="utf-8"?> &

Android基础知识之frame动画效果

上一篇我们说了Android中的tween动画,这一篇我们说说frame动画,frame动画主要是实现了一种类似于gif动画的效果,就是多张图按预先设定好的时间依次连续显示. 新建一个android项目,名字叫做frameTest,在res文件夹下新建一个文件夹叫做anim,我们的frame动画的xml文件就放在这里. 在anim中新建一个frame.xml文件,内容如下: <?xml version="1.0" encoding="utf-8"?> &