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. JDK源码分析(三)——HashMap 下(基于JDK8)

    目录 概述 内部字段及构造方法 哈希值与索引计算 存储元素 扩容 删除元素 查找元素 总结 概述   在上文我们基于JDK7分析了HashMap的实现源码,介绍了HashMap的加载因子loadFac ...

  2. Expression表达式树 案例

    1,Expression.Invoke //运用委托或Lambda表达式 System.Linq.Expressions.Expression<Func<; System.Linq.Exp ...

  3. QQ邮件定时发送天气预报

    1.首先利用request库去请求数据,天气预报使用的是和风天气的API(www.heweather.com/douments/api/s6/weather-forecast) 2.利用python的 ...

  4. Python发送带附件的邮件

    看别人的博客就不要在往别人的邮箱里发东西了行不行, 有点素质可以吗!!! 写出来分享还不知道珍惜!!!!! #-*-encoding:utf-8 -*- import os import smtpli ...

  5. Tkinter制作简单的python编辑器

    想要制作简单的python脚本编辑器,其中文字输入代码部分使用Tkinter中的Text控件即可实现. 但是问题是,如何实现高亮呢?参考python自带的编辑器:python27/vidle文件夹中的 ...

  6. bzoj 3209 数位DP+欧拉定理

    枚举1的个数,统计有那么多1的数的个数 /************************************************************** Problem: 3209 Us ...

  7. 【bzoj2005】 [Noi2010]能量采集 数学结论(gcd)

    [bzoj2005] [Noi2010]能量采集 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnli ...

  8. BZOJ 1003 物流运输trans dijstra+dp

    1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3896  Solved: 1608[Submit] ...

  9. ZOJ 3626 Treasure Hunt I 树上DP

    E - Treasure Hunt I Time Limit:2000MS Memory Limit:65536KB Description Akiba is a dangerous country ...

  10. SGU 405 Totalizator

    405. Totalizator Time limit per test: 0.25 second(s)Memory limit: 65536 kilobytes input: standardout ...