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. SQL注入使用Django中继数据包bypassWAF

    原理 本人基于文章bypassword的文章在HTTP协议层面绕过WAF所编写一款工具. 环境 Python3.7.0 Django 2.1 Requests 使用范围 POST注入 可以分块传输的漏 ...

  2. hdu-1540线段树刷题

    title: hdu-1540线段树刷题 date: 2018-10-18 19:55:21 tags: acm 刷题 categories: ACM-线段树 概述 哇,,,这道线段树的题可以说是到目 ...

  3. python io 模块之 open() 方法(好久没写博客了)

    io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True),打开file ...

  4. BZOJ.5311.贞鱼(DP 决策单调)

    题目链接 很容易写出\(O(n^2k)\)的DP方程.然后显然决策点是单调的,于是维护决策点就可以了.. 这个过程看代码或者别的博客吧我不写了..(其实是忘了) 这样复杂度\(O(nk\log n)\ ...

  5. Codeforces Round #463

    A - Palindromic Supersequence /* 题目大意:给出一个串,构造一个包含该串的回文串 */ #include <cstdio> #include <alg ...

  6. BZOJ 4066 简单题(KD树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4066 [题目大意] 要求维护矩阵内格子加点和矩阵查询 [题解] 往KD树上加权值点,支 ...

  7. Windows下修改Git bash的HOME路径

    Windows中使用http://git-scm.com/安装Git bash工具,默认的HOME和~路径一般都是C:\Users\用户名,每次得用命令切换到常用的Repository下,此操作重复而 ...

  8. VC被控制时关闭极域电子教室、破解联想硬盘保护系统密码(上)

    <[原]关于VC运行时关闭极域电子教室的改进方法> 本文将讲资料和方法,具体实现和破解联想硬盘保护系统密码在(下)中,有关破解联想硬盘保护系统(删除它)的方法很简单,用硬盘保护卡克星就可以 ...

  9. centos7下redis-2.8.13安装笔记

    安装gcc 执行命令:yum install gcc 中间有两次提示,要求输入:yes 或 y,我们按照提示来就可以 至此安装成功 注意:如果不装gcc,解压redis后执行make命令会报错,如下图 ...

  10. mybatis如何根据mapper接口生成其实现类

    SpringBoot集成mybatis mybatis的statement的解析与加载 mybatis如何根据mapper接口生成其实现类 mybatis的mapper返回map结果集 mybatis ...