欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

安卓学习笔记--- Android加载Gif动画android-gif-drawable的使用

程序员文章站 2022-03-24 18:47:27
...

博客转载地址:

http://blog.csdn.net/xiaomai949804781/article/details/52872409

还有一篇博客,也很值得借鉴:

http://blog.csdn.net/zhangphil/article/details/50819930

Android加载Gif动画android-gif-drawable的使用

目前支持Gif播放的开源库还是有的,不过经分析:

GifView:如果Gif图片太大会导致OOM;

SimpleDraweeView:是由Facebook提供的,它的弊端是:不支持 wrap_content 属性。


android-gif-drawable在github上的官方主页地址:

https://github.com/koral--/android-gif-drawable ,该地址上的库及代码是针对Android Studio的。


概述:

  • android-gif-drawable是通过JNI来渲染帧的,这种方式比使用WebView或者Movie效率要高

要求

  • Android 2.3+ (API level 9+)*
  • 如果使用GifTextureView, Android 4.0+ (API level 14+) ,支持硬件加速渲染
  • 如果使用GifTexImage2D,OpenGL ES 2.0+

使用步骤:

Gradle (Android Studio)

  • 在你的项目的“build.gradle”文件中插入以下依赖
dependencies {
    compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.2'
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 官方要求在你的项目的“build.gradle”文件的顶部加入如下声明,配置Maven的*存储库(ps:我并没有这样做,同样可以使用)
buildscript {
    repositories {
        mavenCentral()
    }
}
allprojects {
    repositories {
        mavenCentral()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

GifImageView的使用

最简单的方法是使用GifImageView(或GifImageButton)和使用ImageView的方法是一样的:

<pl.droidsonroids.gif.GifImageView
    android:id="@+id/activity_gif_giv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:src="@drawable/anim"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

GifImageView会自动识别”Android:src”或者”android:background”的内容是否Gif文件,如果是Gif就播放Gif文

件,否则就像我们熟悉的ImageView或者ImageButton一样展示。这样其实Gif就已经可以播放了,就这么简单。

当然,你也可以在Java代码中通过调用setImageResource(int resId) 或者setBackgroundResource(int resId)

为GifImageView, GifImageButton 和GifTextView 设置Gif的资源。除了这两种方法以外,还支持多种来源,例如:

// 从Assets中获取
GifDrawable gifFromAssets = new GifDrawable(getAssets(), "anim.gif");
// 从drawable或者raw中获取
GifDrawable gifFromResource = new GifDrawable(getResources(), R.drawable.anim);
// 从文件中获取
File gifFile = new File(getFilesDir(), "anim.gif");
GifDrawable gifFromFile = new GifDrawable(gifFile);
//从输入流中获取,如果GifDrawable不再使用,输入流会自动关闭。另外,你还可以通过调用recycle()关闭不再使用的输入流
InputStream inputStream = new FileInputStream(gifFile);
BufferedInputStream bis = new BufferedInputStream(inputStream, 1024 * 1024);
GifDrawable gifFromStream = new GifDrawable(bis);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以发现,我们获取到的都是一个GifDrawable对象,这个GifDrawable是干什么的呢?我们首先说Drawable,

大家不陌生吧,IamgeView.setImageDrawable(Drawable drawable);相信这个方法也都使用过,那么好了

GifDrawable和我们平时使用的Drawable的用途是一样的,调用gifImageView.setImageDrawable()就可以

了。当然,GifDrawable还支持其他的方式,这里就不在赘述,有兴趣的可以到GitHub查看

注意:GifDrawable所引用的资源需要能自动跳转到第一帧,也就是支持循环播放


动画控制

GifDrawable实现了Animatable和MediaPlayerControl的接口,所以我们可以使用它们的方法,如:

  • stop() - 停止动画, 可以在任何线程调用
  • start() - 开始动画, 可以在任何线程调用
  • isRunning() - 返回动画是否正在运行
  • reset() - rewinds the animation, does not restart stopped one
  • setSpeed(float factor) - 设置动画的播放速度, 例如: 传入参数 2.0f 将会2倍速度播放
  • seekTo(int position) - 跳转到指定的位置播放
  • getDuration() - 返回动画的总时间
  • getCurrentPosition() - 返回当前已经播放的时间

使用MediaPlayerControl控制动画的播放

我们可以像使用VideoView一样,通过MediaPlayer控制Gif的播放并展示它的播放进度

    private GifImageView mGifImageView;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        mGifImageView = (GifImageView) findViewById(R.id.activity_gif_giv);
        try {
            GifDrawable gifDrawable = new GifDrawable(getAssets(), "anim.gif");
            mGifImageView.setImageDrawable(gifDrawable);
            final MediaController mediaController = new MediaController(this);
            mediaController.setMediaPlayer((GifDrawable) mGifImageView.getDrawable());
            /**
             * 也许你会像我一样,当看到上面一行代码时会纳闷,为什么setMediaPalyer传入的参数会是一个
             * GifDrawable对象呢,它需要的参数类型是MediaPlayerControl。。。
             * 还永德我们前面提到GifDrawable实现了MediaPlayerControl接口吗?
             * 嗯。。。哦,,,恍然大明白了
             */
            mediaController.setAnchorView(mGifImageView);
            mGifImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mediaController.show();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

获取Gif的元数据

GifDrawable提供以下方法,用于获取Gif的元数据

  • getLoopCount() - 返回循环的次数
  • getNumberOfFrames() - 返回动画的总帧数(最小为1)
  • getComment() - 返回注释文本(如果没有返回null)
  • getFrameByteCount() - 返回可用于存储每帧的像素的最小字节数
  • getAllocationByteCount() - 返回分配给用于存储gifdrawable像素的内存字节数
  • getInputSourceByteCount() - 返回支持输入数据的字节数
  • toString() - 返回关于图像大小和帧数量(用于调试目的)

一个GifDrawable实例被多个GifImageView关联,那么通常只胡最后一个GifImageView会播放动画,而前面

的GifImageView只会显示第一帧。为了解决这个问题multicallback出场了:

        MultiCallback multiCallback = new MultiCallback();
        try {
            final GifDrawable gifDrawable = new GifDrawable(getAssets(), "anim.gif");
            mGifImageView.setImageDrawable(gifDrawable);
            multiCallback.addView(mGifImageView);

            mGifImageView2.setImageDrawable(gifDrawable);
            multiCallback.addView(mGifImageView2);
            gifDrawable.setCallback(multiCallback);
        } catch (IOException e) {
            e.printStackTrace();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样两个动画都动起来了。MultiCallBack还可以同时控制两个GifImageView,比如,动画播放5秒后,全部停止。

        multiCallback.scheduleDrawable(gifDrawable, new Runnable() {
           @Override
           public void run() {
              gifDrawable.stop();
           }
        }, 5 * 1000);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

GifDrawable

  • recycle() - 释放内存和Bitmap的作用方法一样
  • isRecycled() - 检查是否已经被回收
  • getError() - 返回最新的错误细节