简体   繁体   English

显示动画 GIF

[英]Display Animated GIF

I want to display animated GIF images in my aplication.我想在我的应用程序中显示动画 GIF 图像。 As I found out the hard way Android doesn't support animated GIF natively.正如我发现 Android 本身不支持动画 GIF 的艰难方式。

However it can display animations using AnimationDrawable :但是它可以使用AnimationDrawable显示动画:

Develop > Guides > Images & Graphics > Drawables Overview 开发 > 指南 > 图像和图形 > Drawables 概述

The example uses animation saved as frames in application resources but what I need is to display animated gif directly.该示例使用在应用程序资源中保存为帧的动画,但我需要的是直接显示动画 gif。

My plan is to break animated GIF to frames and add each frame as drawable to AnimationDrawable.我的计划是将动画 GIF 分解为帧并将每个帧添加为可绘制到 AnimationDrawable。

Does anyone know how to extract frames from animated GIF and convert each of them into Drawable ?有谁知道如何从动画 GIF 中提取帧并将它们转换为Drawable

Android actually can decode and display animated GIFs, using android.graphics.Movie class. Android 实际上可以解码和显示动画 GIF,使用 android.graphics.Movie 类。

This is not too much documented, but is in SDK Reference .这没有太多记录,但在SDK Reference 中 Moreover, it is used in Samples in ApiDemos in BitmapDecode example with some animated flag.此外,它在带有一些动画标志的BitmapDecode示例中的 ApiDemos 中的示例中使用。

UPDATE:更新:

Use glide:使用滑行:

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.0.0'
}

usage:用法:

Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));

see docs查看文档

also put (main/assets/htmls/name.gif) [with this html adjust to the size]也把 (main/assets/htmls/name.gif) [用这个 html 调整到大小]

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

declare in your Xml for example like this (main/res/layout/name.xml): [you define the size, for example]例如像这样在你的 Xml 中声明(main/res/layout/name.xml):[你定义大小,例如]

<WebView
android:layout_width="70dp"
android:layout_height="70dp"
android:id="@+id/webView"
android:layout_gravity="center_horizontal" />

in your Activity put the next code inside of onCreate在您的 Activity 中将下一个代码放在 onCreate 中

web = (WebView) findViewById(R.id.webView); 
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///android_asset/htmls/name.html");

if you want load dynamically you have to load the webview with data:如果要动态加载,则必须使用数据加载 webview:

// or "[path]/name.gif" (e.g: file:///android_asset/name.gif for resources in asset folder), and in loadDataWithBaseURL(), you don't need to set base URL, on the other hand, it's similar to loadData() method.
String gifName = "name.gif";
String yourData = "<html style=\"margin: 0;\">\n" +
        "    <body style=\"margin: 0;\">\n" +
        "    <img src=" + gifName + " style=\"width: 100%; height: 100%\" />\n" +
        "    </body>\n" +
        "    </html>";
// Important to add this attribute to webView to get resource from outside.
webView.getSettings().setAllowFileAccess(true);

// Notice: should use loadDataWithBaseURL. BaseUrl could be the base url such as the path to asset folder, or SDCard or any other path, where your images or the other media resides related to your html
webView.loadDataWithBaseURL("file:///android_asset/", yourData, "text/html", "utf-8", null);
// Or if you want to load image from SD card or where else, here is the idea.
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
webView.loadDataWithBaseURL(base + '/', yourData, "text/html", "utf-8", null);

suggestion: is better load gif with static images for more information check https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html建议:最好使用静态图像加载 gif 以获取更多信息,请查看https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

That's it, I hope you help.就是这样,希望能帮到你。

Currently we can use Glide https://github.com/bumptech/glide目前我们可以使用Glide https://github.com/bumptech/glide

I solved the problem by splitting gif animations into frames before saving it to phone, so I would not have to deal with it in Android.我通过在将gif动画保存到手机之前将其拆分为帧来解决该问题,因此我不必在 Android 中处理它。

Then I download every frame onto phone, create Drawable from it and then create AnimationDrawable - very similar to example from my question然后我将每一帧下载到手机上,从中创建 Drawable,然后创建AnimationDrawable - 与我的问题中的示例非常相似

i found a very easy way, with a nice and simple working example here我找到了一个非常简单的方法,这里有一个漂亮而简单的工作示例

display animated widget 显示动画小部件

Before getting it working there are some chages to do do in the code在让它工作之前,在代码中有一些变化要做

IN THE FOLLOWING在以下

    @Override
    public void onCreate(Bundle savedInstanceState){    
        super.onCreate(savedInstanceStated);   
        setContentView(new MYGIFView());
    }    
}

just replace只需更换

setContentView(new MYGIFView());

in

setContentView(new MYGIFView(this));

AND IN并在

public GIFView(Context context) {
    super(context);

Provide your own gif animation file提供您自己的gif动画文件

    is = context.getResources().openRawResource(R.drawable.earth);
    movie = Movie.decodeStream(is);
}

REPLACE THE FIRST LINE IN替换第一行

public MYGIFView(Context context) {

according to the name of the class...根据班级名称...

after done this little changes it should work as for me...完成这个小改动后,它应该对我有用......

hope this help希望这有帮助

Glide 4.6滑翔 4.6

1. To Load gif 1.加载gif

GlideApp.with(context)
            .load(R.raw.gif) // or url
            .into(imageview);

2. To get the file object 2.获取文件对象

GlideApp.with(context)
                .asGif()
                .load(R.raw.gif) //or url
                .into(new SimpleTarget<GifDrawable>() {
                    @Override
                    public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {

                        resource.start();
                      //resource.setLoopCount(1);
                        imageView.setImageDrawable(resource);
                    }
                });

Ways to show animated GIF on Android:在 Android 上显示动画 GIF 的方法:

  • Movie class.电影课。 As mentioned above, it's fairly buggy.如上所述,它相当有缺陷。
  • WebView.网络视图。 It's very simple to use and usually works.它使用起来非常简单并且通常有效。 But sometimes it starts to misbehave, and it's always on some obscure devices you don't have.但有时它开始行为不端,而且总是在一些你没有的晦涩设备上。 Plus, you can't use multiple instances in any kind of list views, because it does things to your memory.另外,您不能在任何类型的列表视图中使用多个实例,因为它会影响您的记忆。 Still, you might consider it as a primary approach.不过,您可能会将其视为主要方法。
  • Custom code to decode gifs into bitmaps and show them as Drawable or ImageView.用于将 gif 解码为位图并将它们显示为 Drawable 或 ImageView 的自定义代码。 I'll mention two libraries:我会提到两个库:

https://github.com/koral--/android-gif-drawable - decoder is implemented in C, so it's very efficient. https://github.com/koral--/android-gif-drawable - 解码器是用 C 实现的,所以非常高效。

https://code.google.com/p/giffiledecoder - decoder is implemented in Java, so it's easier to work with. https://code.google.com/p/giffiledecoder - 解码器是用 Java 实现的,因此更容易使用。 Still reasonably efficient, even with large files.即使文件很大,仍然相当高效。

You'll also find many libraries based on GifDecoder class.您还会发现许多基于 GifDecoder 类的库。 That's also a Java-based decoder, but it works by loading the entire file into memory, so it's only applicable to small files.这也是一个基于Java的解码器,但它的工作原理是将整个文件加载到内存中,因此它只适用于小文件。

I had a really hard time to have animated gif working in Android.我真的很难在 Android 中使用动画 gif。 I only had following two working:我只有以下两个工作:

  1. WebView网页视图
  2. Ion离子

WebView works OK and really easy, but the problem is it makes the view loads slower and the app would be unresponsive for a second or so. WebView 工作正常而且非常简单,但问题是它会使视图加载速度变慢,并且应用程序会在一秒钟左右没有响应。 I did not like that.我不喜欢那样。 So I have tried different approaches (DID NOT WORK):所以我尝试了不同的方法(不起作用):

  1. ImageViewEx is deprecated! ImageViewEx已弃用!
  2. picasso did not load animated gif毕加索没有加载动画 gif
  3. android-gif-drawable looks great, but it caused some wired NDK issues in my project. android-gif-drawable看起来不错,但它在我的项目中导致了一些有线 NDK 问题。 It caused my local NDK library stop working, and I was not able to fix it它导致我的本地 NDK 库停止工作,我无法修复它

I had some back and forth with Ion ;我和Ion有一些来回; Finally, I have it working, and it is really fast :-)最后,我让它工作了,它真的很快:-)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///android_asset/animated.gif");

Glide

Image Loader Library for Android, recommended by Google.由 Google 推荐的 Android 图像加载程序库。

  • Glide is quite similar to Picasso but this is much faster than Picasso. Glide 与 Picasso 非常相似,但它比 Picasso 快得多。
  • Glide consumes less memory than Picasso. Glide 比 Picasso 消耗更少的内存。

What that Glide has but Picasso doesn't Glide 有但毕加索没有的东西

An ability to load GIF Animation to a simple ImageView might be the most interesting feature of Glide.将 GIF 动画加载到简单 ImageView 的能力可能是 Glide 最有趣的功能。 And yes, you can't do that with Picasso.是的,你不能用毕加索做到这一点。 在此处输入图片说明 Some important links-一些重要的链接——

  1. https://github.com/bumptech/glide https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

使用ImageViewEx ,这是一个使使用 gif 像使用ImageView一样简单的库。

Try this, bellow code display gif file in progressbar试试这个,下面的代码在进度条中显示 gif 文件

loading_activity.xml(in Layout folder) loading_activity.xml(在布局文件夹中)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" >

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/custom_loading"
        android:visibility="gone" />

</RelativeLayout>

custom_loading.xml(in drawable folder) custom_loading.xml(在 drawable 文件夹中)

here i put black_gif.gif(in drawable folder), you can put your own gif here这里我放了 black_gif.gif(在 drawable 文件夹中),你可以把自己的 gif 放在这里

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/black_gif"
    android:pivotX="50%"
    android:pivotY="50%" />

LoadingActivity.java(in res folder) LoadingActivity.java(在 res 文件夹中)

public class LoadingActivity extends Activity {

    ProgressBar bar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading);
        bar = (ProgressBar) findViewById(R.id.progressBar);
        bar.setVisibility(View.VISIBLE);

    }

}

Nobody has mentioned the Ion or Glide library.没有人提到过IonGlide库。 they work very well.他们工作得很好。

It's easier to handle compared to a WebView.与 WebView 相比,它更容易处理。

I have had success with the solution proposed within this article , a class called GifMovieView , which renders a View which can then be displayed or added to a specific ViewGroup .我曾与提出的解决方案的成功这篇文章中,一个叫做类GifMovieView ,这使得一个View则可以显示或添加到特定ViewGroup Check out the other methods presented in parts 2 and 3 of the specified article.查看指定文章的第 2 部分和第 3 部分中介绍的其他方法。

The only drawback to this method is that the antialiasing on the movie is not that good (must be a side-effect of using the "shady" Android Movie Class).这种方法的唯一缺点是电影的抗锯齿效果不是很好(一定是使用“阴暗的”Android Movie类的副作用)。 You are then better off setting the background to a solid color within your animated GIF.然后,您最好在动画 GIF 中将背景设置为纯色。

Some thoughts on the BitmapDecode example... Basically it uses the ancient, but rather featureless Movie class from android.graphics.关于 BitmapDecode 示例的一些想法...基本上它使用来自 android.graphics 的古老但毫无特色的Movie类。 On recent API versions you need to turn off hardware acceleration, as described here .在最近的 API 版本中,您需要关闭硬件加速, 如此处所述 It was segfaulting for me otherwise.否则对我来说是段错误。

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

Here is the BitmapDecode example shortened with only the GIF part.这是仅使用 GIF 部分缩短的 BitmapDecode 示例。 You have to make your own Widget (View) and draw it by yourself.你必须制作自己的Widget(视图)并自己绘制。 Not quite as powerful as an ImageView.不如 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();
            }
        }
    }
}

2 other methods, one with ImageView another with WebView can be found in this fine tutorial .其他 2 种方法,一种使用 ImageView,另一种使用 WebView 可以在这个精美的教程中找到。 The ImageView method uses the Apache licensed android-gifview from Google Code. ImageView 方法使用来自 Google Code 的 Apache 许可的android-gifview

@PointerNull gave good solution, but it is not perfect. @PointerNull 给出了很好的解决方案,但它并不完美。 It doesn't work on some devices with big files and show buggy Gif animation with delta frames on pre ICS version.它在某些具有大文件的设备上不起作用,并且在 ICS 之前的版本上显示带有增量帧的错误 Gif 动画。 I found solution without this bugs.我找到了没有这个错误的解决方案。 It is library with native decoding to drawable: koral's android-gif-drawable .它是具有原生解码到 drawable 的库: koral 的 android-gif-drawable

Put it into a WebView, it has to be able to display it correctly, since the default browser supports gif files.把它放到一个WebView中,它必须能够正确显示它,因为默认浏览器支持gif文件。 (Froyo+, if i am not mistaken) (Froyo+,如果我没记错的话)

There are two options to load animated gifs into our Android apps有两个选项可以将 gif 动画加载到我们的 Android 应用程序中

1)Using Glide to load the gif into an ImageView . 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) Using an html to load the gif into a WebView 2)使用html将gif加载到WebView

Create the html with the address to the .gif file:使用 .gif 文件的地址创建 html:

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

store this file into the assets directory:将此文件存储到资产目录中:

在此处输入图片说明

The load this html into the WebView of your application:将此 html 加载到应用程序的 WebView 中:

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

Heres is a complete example of this two options .这是这两个选项完整示例

在此处输入图片说明

For only android API (Android Pie)28 and +仅适用于 android API (Android Pie)28 和 +

use AnimatedImageDrawable as 使用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 code, add a ImageView 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 is a child of Drawable and created by ImageDecoder.decodeDrawable AnimatedImageDrawable是 Drawable 的子类,由ImageDecoder.decodeDrawable创建

ImageDecoder.decodeDrawable which further required the instance of ImageDecoder.Source created by ImageDecoder.createSource . ImageDecoder.decodeDrawable进一步需要由ImageDecoder.Source创建的ImageDecoder.createSource实例。

ImageDecoder.createSource can only take source as a name, ByteBuffer, File, resourceId, URI, ContentResolver to create source object and uses it to create AnimatedImageDrawable as Drawable (polymorphic call) ImageDecoder.createSource只能以 source 为名称,ByteBuffer、File、resourceId、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)

Note: You can also create Bitmap using ImageDecoder#decodeBitmap .注意:您还可以使用ImageDecoder#decodeBitmap创建Bitmap

Output:输出:

AnimatedDrawable also supports resizing, frame and color manipulation AnimatedDrawable 还支持调整大小、框架和颜色操作

I think the better library to handle gif files is this one: by koral我认为处理 gif 文件的更好的库是这个:by koral

Used it and i'm successful and this library is dedicated to GIF'S;使用它,我成功了,这个库专用于 GIF ; but where as the picasso and glide are general purpose image framework;但是picasso 和 glide通用图像框架; so i think the developers of this library have entirely concentrated on gif files所以我认为这个库的开发者完全专注于 gif 文件

Use fresco.使用壁画。 Here's how to do it:这是如何做到的:

http://frescolib.org/docs/animations.html http://frescolib.org/docs/animations.html

Here's the repo with the sample:这是带有示例的回购:

https://github.com/facebook/fresco/tree/master/samples/animation https://github.com/facebook/fresco/tree/master/samples/animation

Beware fresco does not support wrap content!当心壁画不支持换行内容!

Just wanted to add that the Movie class is now deprecated.只是想补充一点,现在已弃用Movie类。

This class was deprecated in API level P.此类在 API 级别 P 中已弃用。

It is recommended to use this推荐使用这个

AnimatedImageDrawable AnimatedImageDrawable

Drawable for drawing animated images (like GIF). Drawable 用于绘制动画图像(如 GIF)。

Something I did for showing gifs in apps.我为在应用程序中显示 gif 所做的一些事情。 I extended ImageView so people can use its attributes freely.我扩展了 ImageView 以便人们可以自由地使用它的属性。 It can show gifs from url or from the assets directory.它可以显示来自 url 或资产目录的 gif。 The library also makes it easy for extending classes to inherit from it and extend it to support different methods to initialize the gif.该库还使扩展类可以轻松地从它继承并扩展它以支持不同的方法来初始化 gif。

https://github.com/Gavras/GIFView https://github.com/Gavras/GIFView

There's a little guide on the github page. github页面上有一个小指南。

It was also published on Android Arsenal:它也发布在 Android 阿森纳:

https://android-arsenal.com/details/1/4947 https://android-arsenal.com/details/1/4947

Use example:使用示例:

From XML:来自 XML:

<com.whygraphics.gifview.gif.GIFView xmlns:gif_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_activity_gif_vie"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="center"
        gif_view:gif_src="url:http://pop.h-cdn.co/assets/16/33/480x264/gallery-1471381857-gif-season-2.gif" />

In the activity:在活动中:

    GIFView mGifView = (GIFView) findViewById(R.id.main_activity_gif_vie);

    mGifView.setOnSettingGifListener(new GIFView.OnSettingGifListener() {
                @Override
                public void onSuccess(GIFView view, Exception e) {
                    Toast.makeText(MainActivity.this, "onSuccess()", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(GIFView view, Exception e) {

        }
});

Setting the gif programmatically:以编程方式设置 gif:

mGifView.setGifResource("asset:gif1");

我通过在帧中分割 gif 并使用标准的 android 动画解决了这个问题

Similar to what @Leonti said, but with a little more depth:类似于@Leonti所说的,但更深入一点:

What I did to solve the same problem was open up GIMP, hide all layers except for one, export it as its own image, and then hide that layer and unhide the next one, etc., until I had individual resource files for each one.我为解决同样的问题所做的是打开 GIMP,隐藏除一层之外的所有层,将其导出为自己的图像,然后隐藏该层并取消隐藏下一层,等等,直到我为每个层都有单独的资源文件. Then I could use them as frames in the AnimationDrawable XML file.然后我可以将它们用作 AnimationDrawable XML 文件中的帧。

Easiest way - Can be consider the below code最简单的方法 - 可以考虑下面的代码

We can take advantage of Imageview setImageResource , refer below code for the same.我们可以利用 Imageview setImageResource ,参考下面的代码。

The below code can be used to show the image like gif incase if you have the multiple split image of gif.如果您有多个分割的 gif 图像,以下代码可用于显示 gif 之类的图像。 Just split the gif into individual png from a online tool and put image in the drawable like the below order只需从在线工具中将 gif 拆分为单个 png 并将图像放入可绘制对象中,如下所示

image_1.png, image_2.png, etc. image_1.png、image_2.png 等

Have the handler to change the image dynamically.让处理程序动态更改图像。

int imagePosition = 1;
    Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            public void run() {
                updateImage();
            }
        };




    public void updateImage() {

                appInstance.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        int resId = getResources().getIdentifier("image_" + imagePosition, "drawable", appInstance.getPackageName());
                        gifImageViewDummy.setImageResource(resId);
                        imagePosition++;
    //Consider you have 30 image for the anim
                        if (imagePosition == 30) {
//this make animation play only once
                            handler.removeCallbacks(runnable);

                        } else {
    //You can define your own time based on the animation
                            handler.postDelayed(runnable, 50);
                        }

//to make animation to continue use below code and remove above if else
// if (imagePosition == 30)
//imagePosition = 1;
// handler.postDelayed(runnable, 50);
// 
                    }
                });
              }

The easy way to display animated GIF directly from URL to your app layout is to use WebView class.直接从 URL 显示动画 GIF 到您的应用程序布局的简单方法是使用 WebView 类。

Step 1: In your layout XML第 1 步:在您的布局 XML 中

 <WebView android:id="@+id/webView" android:layout_width="50dp" android:layout_height="50dp" />

Step 2: In your Activity第 2 步:在您的活动中

 WebView wb; wb = (WebView) findViewById(R.id.webView); wb.loadUrl("https://.......);

Step 3: In your Manifest.XML make Internet permission第 3 步:在您的 Manifest.XML 中设置 Internet 权限

 <uses-permission android:name="android.permission.INTERNET" />

Step 4: In case you want to make your GIF background transparent and make GIF fit to your Layout第 4 步:如果您想让 GIF 背景透明并使 GIF 适合您的布局

 wb.setBackgroundColor(Color.TRANSPARENT); wb.getSettings().setLoadWithOverviewMode(true); wb.getSettings().setUseWideViewPort(true);

If you want to use Glide for loading gif:如果你想使用 Glide 加载 gif:

Glide.with(this)
        .asGif()
        .load(R.raw.onboarding_layers) //Your gif resource
        .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
        .listener(new RequestListener<GifDrawable>() {
            @Override
            public boolean onLoadFailed(@Nullable @org.jetbrains.annotations.Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
                resource.setLoopCount(1);
                return false;
            }
        })
        .into((ImageView) view.findViewById(R.id.layer_icons));

To save resources there is glide library for.为了节省资源,有滑翔库。 Have no idea why to use anything else, especialy webview to show image only.不知道为什么要使用其他任何东西,尤其是 webview 只显示图像。 Glide is perfect and easy library that prepares animated drawable from gif and put it directly to imageview. Glide 是一个完美且简单的库,它可以从 gif 中准备可绘制动画并将其直接放入 imageview。 The logic of gifdrawable handle animation itself. gifdrawable 处理动画本身的逻辑。 Gif have lzw ziped raw rgb data of an animation inside. Gif 已经 lzw 压缩了动画的原始 rgb 数据。 There is no reason for complicated usage of webview and manage more files to show just a gif file in app.没有理由复杂使用 webview 并管理更多文件以在应用程序中仅显示 gif 文件。

You may use GifAnimationDrawable library found in this link - https://github.com/Hipmob/gifanimateddrawable , and which convert any gif to AnimationDrawable.您可以使用此链接中的 GifAnimationDrawable 库 - https://github.com/Hipmob/gifanimateddrawable ,并将任何 gif 转换为 AnimationDrawable。 Enjoy :)享受 :)

First of all the Android browser should support Animated GIFs.首先,Android 浏览器应该支持动画 GIF。 If it doesn't then it's a bug!如果没有,那就是一个错误! Have a look at the issue trackers.查看问题跟踪器。

If you're displaying these animated GIFs outside of a browser it might be a different story.如果您在浏览器之外显示这些动画 GIF,则可能是另一回事。 To do what you're asking would require external library that supports the decoding of Animated GIFs.要执行您的要求,需要支持动画 GIF 解码的外部库。

The first port of call would be to look at Java2D or JAI (Java Advanced Imaging) API, although I would be very surprised if Android Dalvik would support those libraries in your App.第一个调用端口是查看 Java2D 或 JAI(Java 高级成像)API,尽管如果 Android Dalvik 支持您的应用程序中的这些库,我会感到非常惊讶。

public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private Bitmap mBitmap;
    private Bitmap mBitmap2;
    private Bitmap mBitmap3;
    private Bitmap mBitmap4;
    private Drawable mDrawable;

    private Movie mMovie;
    private long mMovieStart;

    // Set to false to use decodeByteArray
    private static final boolean DECODE_STREAM = true;

    private static byte[] streamToBytes(InputStream is) {
      ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
      byte[] buffer = new byte[1024];
      int len;
      try {
        while ((len = is.read(buffer)) >= 0) {
          os.write(buffer, 0, len);
        }
      } catch (java.io.IOException e) {
      }
      return os.toByteArray();
    }

    public SampleView(Context context) {
      super(context);
      setFocusable(true);

      java.io.InputStream is;
      is = context.getResources().openRawResource(R.drawable.icon);

      BitmapFactory.Options opts = new BitmapFactory.Options();
      Bitmap bm;

      opts.inJustDecodeBounds = true;
      bm = BitmapFactory.decodeStream(is, null, opts);

      // now opts.outWidth and opts.outHeight are the dimension of the
      // bitmap, even though bm is null

      opts.inJustDecodeBounds = false; // this will request the bm
      opts.inSampleSize = 4; // scaled down by 4
      bm = BitmapFactory.decodeStream(is, null, opts);

      mBitmap = bm;

      // decode an image with transparency
      is = context.getResources().openRawResource(R.drawable.icon);
      mBitmap2 = BitmapFactory.decodeStream(is);

      // create a deep copy of it using getPixels() into different configs
      int w = mBitmap2.getWidth();
      int h = mBitmap2.getHeight();
      int[] pixels = new int[w * h];
      mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
      mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_8888);
      mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_4444);

      mDrawable = context.getResources().getDrawable(R.drawable.icon);
      mDrawable.setBounds(150, 20, 300, 100);

      is = context.getResources().openRawResource(R.drawable.animated_gif);

      if (DECODE_STREAM) {
        mMovie = Movie.decodeStream(is);
      } else {
        byte[] array = streamToBytes(is);
        mMovie = Movie.decodeByteArray(array, 0, array.length);
      }
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(0xFFCCCCCC);

      Paint p = new Paint();
      p.setAntiAlias(true);

      canvas.drawBitmap(mBitmap, 10, 10, null);
      canvas.drawBitmap(mBitmap2, 10, 170, null);
      canvas.drawBitmap(mBitmap3, 110, 170, null);
      canvas.drawBitmap(mBitmap4, 210, 170, null);

      mDrawable.draw(canvas);

      long now = android.os.SystemClock.uptimeMillis();
      if (mMovieStart == 0) { // first time
        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, getWidth() - mMovie.width(), getHeight()
            - mMovie.height());
        invalidate();
      }
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

  public PictureLayout(Context context) {
    super(context);
  }

  public PictureLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM