Movie 类

官方对这个类连一句介绍都没有,并且所有的方法也没有一行注释,可见多么不受重视!


package android.graphics;
直接继承自Object,直接继承自Object的基本上都是工具类。

Android的ImageView无法直接加载Gif图片,鉴于此,Android社区开发者为解决此问题贡献了很多解决方案,其中一种比较简易的做法是通过Android中的Movie类把一个gif图片当作一个原始的资源加载到Movie,然后Movie将其解析为Movie帧进行加载。

Movie其实管理着GIF动画中的多个帧,只需要通过 setTime() 一下就可以让它在draw()的时候绘出相应的那帧图像,通过当前时间与duration之间的换算关系,便可实现GIF动起来的效果。

对于比较小的gif图片使用此方法还是可以的,要是大的话,建议还是把gif图片转换成一帧一帧的png图片,然后通过animation播放。

简单的利用Movie播放GIF图的控件

setContentView(new CustomGifView(this, R.drawable.ic_launcher)); //显示普通图片
setContentView(new CustomGifView(this, R.drawable.gif1)); //显示gif动图
/**
* 自定义可以循环播放gif动画的View,可以像使用其他控件一样使用
* @author 白乾涛
*/
public class CustomGifView extends View {
private Movie mMovie;
private long mMovieStart;
private int resId;

public CustomGifView(Context context, int resId) {
super(context);
this.resId = resId;
setLayerType(View.LAYER_TYPE_SOFTWARE, null);//必须关闭硬件加速
mMovie = Movie.decodeStream(getResources().openRawResource(resId));//创建Movie对象
}

public void onDraw(Canvas canvas) {
long now = SystemClock.uptimeMillis();//系统当前时刻
//第一次播放
if (mMovieStart == 0) mMovieStart = now;//动画开始的时间
if (mMovie != null) {
int dur = mMovie.duration();//动画持续的时间,也就是完成一次动画的时间
if (dur == 0) dur = 1000;
int relTime = (int) ((now - mMovieStart) % dur);//注意这是取余操作,这才能算出当前这次重复播放的第一帧的时间
mMovie.setTime(relTime);//设置相对本次播放第一帧时间,根据这个时间来决定显示第几帧
mMovie.draw(canvas, 0, 0);
invalidate();
} else {//如果指定的资源不是gif图片,也就是说是普通的图片,则需要手动绘制此图片
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), resId), getMatrix(), new Paint());
}
}
}

Movie 类的 API

  • static Movie decodeByteArray(byte[] data, int offset, int length)
  • static Movie decodeFile(String pathName)
  • static Movie decodeStream(InputStream is)
  • void draw(Canvas canvas, float x, float y, Paint paint)
  • void draw(Canvas canvas, float x, float y)
  • int duration()
  • int height()
  • boolean isOpaque()
  • boolean setTime(int relativeMilliseconds)
  • int width()

开源库 android-gif-drawable

底层解码使用C实现,极大的提高了解码效率,同时很大程度上避免了OOM。

Views and Drawable for displaying animated GIFs on Android
Bundled GIFLib via JNI is used to render frames. This way should be more efficient than WebView or Movie classes.

Requirements
  • Android 2.3+ (API level 9+)
  • for GifTextureView Android 4.0+ (API level 14+) and hardware-accelerated rendering渲染
  • for GifTexImage2D OpenGL ES 2.0+
Building from source
  • Android NDK needed to compile native sources

配置build.gradle

Insert the following dependency to build.gradle file of your project.
  1. dependencies {
  2.     compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.6'
  3. }

Note that Maven central repository should be defined eg. in top-level build.gradle like this:

  1. buildscript {
  2.     repositories {
  3.         mavenCentral()
  4.     }
  5. }
  6. allprojects {
  7.     repositories {
  8.         mavenCentral()
  9.     }
  10. }

XML中使用

The simplest way is to use GifImageView or GifImageButton like a normal ImageView:
<pl.droidsonroids.gif.GifImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gif1"
android:src="@drawable/gif2"/>
If drawables declared by android:src and/or android:background are GIF files then they will be automatically recognized as GifDrawables and animated. If given drawable is not a GIF then mentioned Views work like plain平常的 ImageView and ImageButton.

GifTextView allows you to use GIFs as compound复合的 drawables and background.
<pl.droidsonroids.gif.GifTextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gif1"
android:drawableTop="@drawable/gif2"/>

代码中构造GifDrawable

GifImageView, GifImageButton and GifTextView have also hooks for setters implemented. So animated GIFs can be set by calling setImageResource(int resId) and setBackgroundResource(int resId)

GifDrawable can be constructed directly from various sources:
void constructGifDrawable() throws IOException {
//asset file
GifDrawable gifFromAssets = new GifDrawable(getAssets(), "gif1.gif");

//resource (drawable or raw)
GifDrawable gifFromResource = new GifDrawable(getResources(), R.drawable.gif1);

//Uri
ContentResolver contentResolver = null; //can be null for file:// Uris
GifDrawable gifFromUri = new GifDrawable(contentResolver, null);//gifUri

//byte array
byte[] rawGifBytes = null;
GifDrawable gifFromBytes = new GifDrawable(rawGifBytes);

//FileDescriptor
FileDescriptor fd = new RandomAccessFile("/path/anim.gif", "r").getFD();
GifDrawable gifFromFd = new GifDrawable(fd);

//file path
GifDrawable gifFromPath = new GifDrawable("/path/anim.gif");

//file
File gifFile = new File(getFilesDir(), "gif1.gif");
GifDrawable gifFromFile = new GifDrawable(gifFile);

//AssetFileDescriptor
AssetFileDescriptor afd = getAssets().openFd("gif1.gif");
GifDrawable gifFromAfd = new GifDrawable(afd);

//InputStream (it must support marking)
InputStream sourceIs = null;
BufferedInputStream bis = new BufferedInputStream(sourceIs, 1024);//GIF_LENGTH
GifDrawable gifFromStream = new GifDrawable(bis);

//direct ByteBuffer
ByteBuffer rawGifByteBuffer = null;
GifDrawable gifFromByteBuffer = new GifDrawable(rawGifByteBuffer);
}

InputStreams are closed automatically in finalizer if GifDrawable is no longer needed so you don't need to explicitly明确的 close them. Calling recycle() will also close underlying潜在的 input source.

Note that all input sources need to have ability to rewind倒回 to the beginning. It is required to correctly play animated GIFs (where animation is repeatable) since subsequent随后的 frames are decoded on demand from source.

动画过程控制 Animation control

GifDrawable implements an Animatable and MediaPlayerControl so you can use its methods and more:
  • stop() - stops the animation, can be called from any thread
  • start() - starts the animation, can be called from any thread
  • isRunning() - returns whether animation is currently running or not
  • reset() - rewinds the animation, does not restart stopped one
  • setSpeed(float factor) - sets new animation speed factor, eg. passing 2.0f will double the animation speed
  • seekTo(int position) - seeks animation (within current loop) to given position (in milliseconds)
  • getDuration() - returns duration of one loop of the animation
  • getCurrentPosition() - returns elapsed time from the beginning of a current loop of animation

使用 MediaPlayerControl

Standard controls for a MediaPlayer (like in VideoView) can be used to control GIF animation and show its current progress.
Just set GifDrawable as MediaPlayer on your MediaController like this:
@BindView(R.id.gif) GifImageView gifView;
android.widget.MediaController mc;
mc = new MediaController(this);
mc.setMediaPlayer((pl.droidsonroids.gif.GifDrawable) gifView.getDrawable());
mc.setAnchorView(gifView);
mc.show();

获取GIF元数据

Retrieving GIF metadata
  • getLoopCount() - returns a loop count as defined in NETSCAPE 2.0 extension
  • getNumberOfFrames() - returns number of frames (at least 1)
  • getComment() - returns comment text (null if GIF has no comment)
  • getFrameByteCount() - returns minimum number of bytes that can be used to store pixels of the single frame
  • getAllocationByteCount() - returns size (in bytes) of the allocated memory used to store pixels of given GifDrawable
  • getInputSourceByteCount() - returns length (in bytes) of the backing input data
  • toString() - returns human readable information about image size and number of frames (intended for debugging purpose)

一个GifDrawable用在多个View上

Associating single GifDrawable instance with multiple Views:
Normally single GifDrawable instance associated with multiple Views will animate only on the last one. To solve that create MultiCallback instance, add Views to it and set callback for given drawable, eg.:
MultiCallback multiCallback = new MultiCallback();
imageView.setImageDrawable(gifDrawable);
multiCallback.addView(imageView);
anotherImageView.setImageDrawable(gifDrawable);
multiCallback.addView(anotherImageView);

gifDrawable.setCallback(multiCallback);

高级API

Advanced
recycle() - provided to speed up freeing memory (like in android.graphics.Bitmap)
isRecycled() - checks whether drawable is recycled
getError() - returns last error details

开源库 Cutta/GifView

Library for playing gifs on Android

Simple android view to display gifs efficiently高效的. You can start, pause and stop gifView.

Inspired by灵感来自 sbakhtiarov/gif-movie-view


这个自定义的View其实主要还是使用了 android.graphics.Movie 这个类。
去看源码时,发现就一个独杆司令GifView,API也就下面几个:

AS中使用

Add these lines on top-level build file
  1. // Top-level build file where you can add configuration options common to all sub-projects/modules.
  2. repositories {
  3.     maven {
  4.         url "https://jitpack.io"
  5.     }
  6. }

On app's build.gradle

  1. compile 'com.github.Cutta:GifView:1.1'
布局和代码中设置:
xmlns:custom="http://schemas.android.com/apk/res-auto"
<com.cunoraz.gifview.library.GifView
android:id="@+id/gif"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
custom:gif="@drawable/gif1"/>
GifView gifView = (GifView) view.findViewById(R.id.gif);
gifView.pause(); //默认为自动播放,可以手动设置 custom:paused="true"

Eclipse中使用

1、把独杆司令GifView拷到项目中
2、把自定义属性拷到attrs.xml中
  1. <declare-styleable name="GifView">
  2. <attr name="gif" format="reference" />
  3. <attr name="paused" format="boolean" />
  4. </declare-styleable>
3、在布局和代码中使用
xmlns:custom="http://schemas.android.com/apk/res/com.bqt"
  1. <com.bqt.GifView
  2. android:id="@+id/gif"
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"
  5. custom:gif="@drawable/gif" />
没啥好说的,简单实用。

附件列表

动态图片 Movie android-gif-drawable GifView的更多相关文章

  1. iOS 播放GIF动态图片!!!!!

    ////////////////////////////////////////////////////////////////////////////////////////// ////  Vie ...

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

    android中显示gif动态图片用到了开源框架GifView 1.拷GifView.jar到自己的项目中. 2.将自己的gif图片拷贝到drawable文件夹 3.在xml文件中设置基本属性: &l ...

  3. Android中显示gif动态图片

    在android中显示一个静态图片比如png jpg等等都很方便,但是如果要显示一个gif 动态图片就需要进行一些处理. 本文是采用自定义view 然后进行重新onDraw方法来实现 首先自定义Vie ...

  4. Android之动态图片

    在Android中,比起静态图片来动态图片会更加生动更加酷炫,因为这种视觉效果,你应该会发现我们手机中大多数应用软件的导航页面也都是采用动态图片来展示.动态图片的格式有gif.png格式等等. 我们就 ...

  5. 动态图片 gif

    简介 android不推荐使用gif图片,一般都是png的,对于gif的图片解析比较消耗资源,但是对于一些动态gif图片的播放,如果比较小的话还是可以的,要是大的话,建议还是把gif图片转换成一帧一帧 ...

  6. 布局之按钮的图片分辨率--Android Studio

    在布局页面,想把取消按钮和确认钮大小一致,刚开始想法是错的,不用在控制层设置,也不用在布局层压缩图片,有两个方法法: 1.直接用美图秀秀“尺寸”功能,修改成另一按钮一样的分辨率. 2.设置按钮相同高度 ...

  7. Android使用Drawable资源之使用ClipDrawable资源 实现进入条

    以前我自定义的进度条(就是咱们现在工程中用的)是从android的源码中扒出来的一个XML,然后把里面的图片给替换了.一直不知道它的具体原理是什么. 今天得空研究了一下,发现它的原理其实就是用的and ...

  8. Android之drawable state各个属性详解

    android:drawable 放一个drawable资源android:state_pressed 是否按下,如一个按钮触摸或者点击.android:state_focused 是否取得焦点,比如 ...

  9. Android动画Drawable Animation

    Drawable Animation是逐帧动画,那么使用它之前必须先定义好各个帧.我们可以通过代码定义,也可以使用xml文件定义,一般使用后者.如下: <?xml version="1 ...

随机推荐

  1. Keras/tensorflow出现‘Loaded runtime CuDNN library: 7.0.5 but source was compiled with: 7.1.14’错误的解决办法

    从tensorflow1.10 升级到1.12版本后,对依赖的CuDNN不兼容产生的问题.鉴于一直使用的是Keras,未使用新版本tensorflow的功能,故果断回退到旧版本. 方法为:pip3 i ...

  2. Linux-数据库4

    存储引擎 什么是存储引擎? mysql中建的库是文件夹,建的表是文件.文件有不同的类型,数据库中的表也有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎. 存储引擎说白了 ...

  3. 【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

    1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description I ...

  4. Ubuntu安装redis和redis-php扩展

    通过apt-get安装的redis使用方法 sudo apt-get install redis-server sudo apt-get install php-redis vim /etc/redi ...

  5. QT学习笔记4:QT中GraphicsView编程

    一.QGraphicsScene 1.QGraphicsScene QGraphicsScene继承自QObject,是一个管理图元的容器,与QGraphicsView合用可以在2D屏幕上显示如线.三 ...

  6. 线性表之单链表C++实现

    线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...

  7. 【Dijkstra】POJ1062-昂贵的聘礼

    由于物品编号从1开始,我们假定0也是一个物品作为起点,它到其它物品的距离就是各个物品的原始价值.开始时,如果两种物品主人的等级限制M在规定范围以内,且j能用i替换,则将优惠价格视作从i到j的一条权值为 ...

  8. 【差分约束系统/SPFA】POJ3169-Layout

    [题目大意] n头牛从小到大排,它们之间某些距离不能大于一个值,某些距离不能小于一个值,求第一头牛和第N头牛之间距离的最大值. [思路] 由题意可以得到以下不等式d[AL]+DL≥d[BL]:d[BD ...

  9. 【POJ】1840:Eqs【哈希表】

    Eqs Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 18299   Accepted: 8933 Description ...

  10. IE11 全新的F12开发者工具

      我讨厌debug,相信也没多少开发者会喜欢.但是当代码出错之后肯定是要找出问题出在哪里的.不过网页开发的时候遇到 BUG 是一件再正常不过的事情了,我们不能保证自己的代码万无一失,于是使用浏览器的 ...