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" />
没啥好说的,简单实用。

附件列表

动态图片 gif的更多相关文章

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

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

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

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

  3. python3抓取异步百度瀑布流动态图片(二)get、json下载代码讲解

    制作解析网址的get def gethtml(url,postdata): header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; ...

  4. Android之动态图片

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

  5. HTML中动态图片切换JQuery实现

    相信很多同学都注意到了,各大新闻或者娱乐网站都含有动态图片切换,那个漂亮的感觉让刚刚学习html的人,都非常好奇和心动.那下面就让我们看一下到底如何实现动态图片切换呢?看一下百度贴吧的效果图吧~ // ...

  6. winfrom播放动态图片

    winfrom是不能直接加载的动态图片的.只能够自己写方法实现. 具体代码如下: using System; using System.Collections.Generic; using Syste ...

  7. Android中显示gif动态图片

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

  8. 用jQuery实现切换动态图片

    1.实现动态图片的切换只需要改变目标图片的路径

  9. 简单的Django向HTML展示动态图片 案例——小白

    目标:通过Django向HTML传送图片展示 我的天哪,真是膈应人,网上的案例都不适合我,感觉所有的解决办法在我这里都不行. 好吧~ 是我菜,看不懂人家的代码,那句话叫啥来着?一本好经被傻和尚念歪了. ...

  10. 【Mac】使用PicGIF制作gif动态图片

    动态图片是我们常常需要的,mac系统下制作gif图片,可以使用PicGIF,AppStore中有一个简单版本免费的 环境与工具 1.mac系统 2.PicGIF Lite(可以在AppStore下载) ...

随机推荐

  1. Linux系统中,main函数的执行过程

    http://blog.csdn.net/rrerre/article/details/6728431

  2. JQUERY1.9学习笔记 之基本过滤器(十一) 奇数选择器

    奇数选择器jQuery( ":odd" ) 例:匹配表格的奇数行. <!DOCTYPE html><html lang="zh-cn"> ...

  3. 文成小盆友python-num7 -常用模块补充 ,python 牛逼的面相对象

    本篇内容: 常用模块的补充 python面相对象 一.常用模块补充 1.configparser模块 configparser 用于处理特定格式的文件,起内部是调用open()来实现的,他的使用场景是 ...

  4. Xcode 快捷键-b

    0.跳到指定行command + L; 1.配置高亮方案:Fonts & Colors 2.键盘快捷键:Key Bindings 3.代码缩进:Re-indent selection.(快捷键 ...

  5. 初窥struts2(二)OGNL表达式

    Struts2总结 Struts2完整的处理流程: 1  客户端发送请求,交给struts2控制器(StrutsPrepareAndExecuteFilter). 2  Filter控制器进行请求过滤 ...

  6. SQLSERVER收缩数据库日志

    数据库名为:EKECMS DUMP TRANSACTION EKECMS WITH NO_LOG;BACKUP LOG EKECMS WITH NO_LOG;DBCC SHRINKDATABASE(E ...

  7. mysql中lock tables与unlock tables

    官网:https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html LOCK TABLES tbl_name [[AS] alias] lock_t ...

  8. Python 命令行非阻塞输入

    很久很久以前,系windows平台下,用C语言写过一款贪食蛇游戏,cmd界面,用kbhit()函数实现非阻塞输入.系windows平台下用python依然可以调用msvcrt.khbit实现非阻塞监听 ...

  9. OpenGl学习总结

    http://wenku.baidu.com/view/5305fe4f866fb84ae45c8dcd.html

  10. mongDB 的使用

    首先是启动 mongdb的service ,不启用的话,使用mong shell 连接的现象是: 启动服务端,指定默认的存储的位置即可: mongod  -- dbpath  F:/store  #数 ...