显示动态GIF

270

我想在我的应用程序中显示动画GIF图像。但很遗憾,Android不支持原生的动画GIF。

不过,Android可以使用AnimationDrawable来显示动画:

开发 > 指南 > 图像和图形 > Drawables概述

示例使用应用程序资源中保存为帧的动画,但我需要直接显示动画GIF。

我的计划是将动画GIF拆分为帧并将每个帧作为drawable添加到AnimationDrawable中。

有人知道如何从动画GIF中提取帧,并将每个帧转换为Drawable吗?


3
你的意思是在安卓中进行,还是使用外部工具从gif文件中提取帧? - Osmund
这绝对是一个 bug,请查看 IssueTracker 获取更多信息。 - Barbarossa
只是为了那些通过搜索可以显示动画GIF的应用程序而来到这里的人:QuickPic - rubo77
1
http://stackoverflow.com/questions/30338258/best-practice-of-showing-gif-in-android/34892679#34892679 - Preetam
使用Fresco来显示GIF https://github.com/facebook/fresco 我认为这是一个简单的解决方案。 - kaitian521
我正在寻找那个问题,并在此处找到了解决方案:在Android应用程序中播放GIF - Roy Doron
29个回答

7

没有人提到IonGlide库,它们工作得非常好。

与WebView相比,它更容易处理。


7

使用ImageViewEx库,这个库可以把使用GIF动图变得像使用ImageView一样简单。


已经被弃用 - Martin Marconcini
我已经查看了这个库的代码,应该可以再使用2年左右。 - NightSkyCode
2
是的,我认为它相对来说还好,只是指出作者决定弃用它(因此不再维护它),指出我们应该使用像 Picasso 这样的东西,这很奇怪,因为 Picasso 是一个图像下载器,当涉及到显示动画 GIF 时,它对你没有任何帮助,与其他许多下载/缓存工具一样。 - Martin Marconcini

5
我已成功使用本文提议的解决方案(位于此文章中),使用名为GifMovieView的类来呈现一个View,该视图可以显示或添加到特定的ViewGroup中。请查看指定文章的第2部分和第3部分中介绍的其他方法。
此方法唯一的缺点是电影的反锯齿效果不太好(可能是使用“不可靠”的Android Movie类的副作用)。因此,最好将动画GIF的背景设置为纯色。

4

关于BitmapDecode示例的一些想法...基本上它使用了来自android.graphics的古老但功能相对简单的Movie类。在最近的API版本中,您需要关闭硬件加速,如此处所述。否则,它会导致段错误。

<activity
            android:hardwareAccelerated="false"
            android:name="foo.GifActivity"
            android:label="The state of computer animation 2014">
</activity>

这里是只包含GIF部分的BitmapDecode示例。你需要自己制作一个小部件(视图),并自行绘制它。不像ImageView那样功能强大。
import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.*;
import android.view.View;

public class GifActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GifView(this));
    }

    static class GifView extends View {
        Movie movie;

        GifView(Context context) {
            super(context);
            movie = Movie.decodeStream(
                    context.getResources().openRawResource(
                            R.drawable.some_gif));
        }
        @Override
        protected void onDraw(Canvas canvas) {   
            if (movie != null) {
                movie.setTime(
                    (int) SystemClock.uptimeMillis() % movie.duration());
                movie.draw(canvas, 0, 0);
                invalidate();
            }
        }
    }
}

还有两种方法可以实现动态图的显示,一种是使用ImageView,另一种是使用WebView,详细信息请参见这篇优秀教程。ImageView方法使用了来自Google Code的Apache许可的android-gifview


1
@luboz,你能告诉我哪种方法适合提高Android性能吗?我想在启动屏幕加载栏中使用动画GIF。所以你能建议一下哪种方法更好吗?另外,我想知道是否可以使用ImageView方法来使用比例类型属性? - Swap-IOS-Android

4

@PointerNull提供了一个好的解决方案,但它并不完美。在一些设备上无法处理大文件,并且在Android 4.0之前的版本中显示带有增量帧的Gif动画时会出现错误。 我找到了一个没有这些问题的解决方法。这是一个具有本地解码功能的库,可以将其转换为可绘制对象:koral's android-gif-drawable


3

仅适用于Android API(Android Pie)28及以上版本

使用AnimatedImageDrawable作为

// ImageView from layout
val ima : ImageView = findViewById(R.id.img_gif)
// create AnimatedDrawable 
val decodedAnimation = ImageDecoder.decodeDrawable(
        // create ImageDecoder.Source object
        ImageDecoder.createSource(resources, R.drawable.tenor))
// set the drawble as image source of ImageView
ima.setImageDrawable(decodedAnimation)
// play the animation
(decodedAnimation as? AnimatedImageDrawable)?.start()

XML代码,添加一个ImageView

<ImageView
    android:id="@+id/img_gif"
    android:background="@drawable/ic_launcher_background" <!--Default background-->
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_width="200dp"
    android:layout_height="200dp" />

AnimatedImageDrawable是Drawable的子类,由ImageDecoder.decodeDrawable创建。

ImageDecoder.decodeDrawable需要ImageDecoder.Source实例,该实例由ImageDecoder.createSource创建。

ImageDecoder.createSource只能使用名称、ByteBuffer、文件、资源ID、URI、ContentResolver作为源来创建源对象,并将其用于创建AnimatedImageDrawable作为Drawable(多态调用)。

static ImageDecoder.Source  createSource(AssetManager assets, String fileName)
static ImageDecoder.Source  createSource(ByteBuffer buffer)
static ImageDecoder.Source  createSource(File file)
static ImageDecoder.Source  createSource(Resources res, int resId)
static ImageDecoder.Source  createSource(ContentResolver cr, Uri uri)

注意:您还可以使用ImageDecoder#decodeBitmap创建Bitmap
输出:

AnimatedDrawable也支持调整大小、帧和颜色处理


2

在我们的Android应用程序中加载动态GIF有两种选择:

1)使用Glide将GIF加载到ImageView中。

    String urlGif = "https://cdn.dribbble.com/users/263558/screenshots/1337078/dvsd.gif";
    //add Glide implementation into the build.gradle file.
    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    Uri uri = Uri.parse(urlGif);
    Glide.with(getApplicationContext()).load(uri).into(imageView);

2) 使用html将gif加载到WebView

创建包含.gif文件地址的html:

<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>

将此文件存储到资产目录中:

在这里输入图片描述

然后在您的应用程序的WebView中加载此html:

    WebView webView =  (WebView)findViewById(R.id.webView);
    webView = (WebView) findViewById(R.id.webView);
    webView.loadUrl("file:///android_asset/html/webpage_gif.html");

这里有一个关于这两个选项的完整示例

在此输入图片描述


2

将其放入WebView中,必须能够正确显示它,因为默认浏览器支持gif文件。(如果我没记错的话,是Froyo+)


这不是真的。并非所有浏览器都支持GIF。 - RichieHH
4
希望我们不需要所有的浏览器...原生浏览器从android 2.2开始就支持它,所以请不要踩我。一个WebView肯定可以显示这个GIF! - keybee

1

我认为处理gif文件的更好的库是 koral

我使用过它并且成功了,这个库专门用于GIF'S;而picasso和glide是通用的图像框架;因此我认为这个库的开发者完全集中在gif文件上。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接