Android的:如何做一个显示给定的URL的大型动画GIF?动画、如何做一个、Android、GIF

2023-09-12 09:10:15 作者:努力就会闪耀

假设我有网址为大gif动画,我想做出这样的活动YouTube的显示以流方式的动画。我如何

Suppose I have the URL for large animated gif and I wanted to make a youtube like activity that displays the animation in a streaming way. How do I

在图像中流? 在得到它做显示屏,实际动画?

我知道的ImageView 是没有答案的,因为它只能显示第一帧。

I know ImageView is not the answer as it only shows the first frame.

奖金将有机会获得其缓冲状态,所以我可以同步声音流,以及 - 这是一个 YTMND 浏览器应用程序的一部分。虽然我可以创建一个跨codeS公众的gif文件到一个更好的格式,我想要的应用程序,而无需额外的依赖关系,以功能服务。

A bonus would be having access to its buffering status so I can synchronize streaming sound as well -- this is part of a YTMND viewer application. While I could create a service that transcodes the public gif files into a nicer format, I'd like the app to function without additional dependencies.

推荐答案

该解决方案的总体草图是使用使用自定义的查看其中提请问了一个电影来自己绘制到画布周期性。

The general sketch of the solution is to use employ custom View which draws asks a Movie to draw itself to the Canvas periodically.

第一步是建设电影实例。有工厂名为德codeStream ,可以使给定一个电影的的InputStream ,但它是不够的从的URLConnection 使用流。如果你试试这个,你会得到一个 IOException异常当电影加载程序试图调用重置在流。黑客,不幸的,因为它是用分离的BufferedInputStream 用手工设置的标记来告诉它保存足够的数据重置不会失败。幸运的是,的URLConnection 能告诉我们有多少数据的期望。我说这个黑客是不幸的,因为它有效地需要整个图像在内存中缓存(这是桌面应用程序没有问题,但它是一个内存受限的移动设备上的一个严重的问题)。

The first step is building the Movie instance. There is factory called decodeStream that can make a movie given an InputStream but it isn't enough to use the stream from a UrlConnection. If you try this you will get an IOException when the movie loader tries to call reset on the stream. The hack, unfortunate as it is, is to use a separated BufferedInputStream with a manually-set mark to tell it to save enough data that reset won't fail. Luckily, the URLConnection can tell us how much data to expect. I say this hack is unfortunate because it effectively requires the entire image to be buffered in memory (which is no problem for desktop apps, but it is a serious issue on a memory-constrained mobile device).

下面是的电影设置code剪断:

Here is a snip of the Movie setup code:

URL url = new URL(gifSource);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bis.mark(conn.getContentLength());
Movie movie = Movie.decodeStream(bis);
bis.close();

接下来,你需要创建一个视图,将显示该电影。对查看与自定义子类的OnDraw 将这样的伎俩(假设它可以访问电影你用previous code)创建。

Next, you need to create a view that will display this Movie. A subclass of View with a custom onDraw will do the trick (assuming it has access to the Movie you created with the previous code).

@Override protected void onDraw(Canvas canvas) {
    if(movie != null) {
        long now = android.os.SystemClock.uptimeMillis();
        int dur = Math.max(movie.duration(), 1); // is it really animated?
        int pos = (int)(now % dur);
        movie.setTime(pos);
        movie.draw(canvas, x, y);
    }
}

视图不会触发本身重绘没有帮助,一味地要求无效()在年底的OnDraw 只是一个能源浪费。在另一个线程(可能是一个你用来下载图像数据),你可以发布消息到主线程,要求该视图在一个稳定的(但不是疯狂)的步伐无效。

The view won't trigger itself to be redrawn without help, and blindly calling invalidate() at the end of onDraw is just an energy waste. In another thread (probably the one you used to download the image data), you can post messages to the main thread, asking for the view to be invalidated at a steady (but not insane) pace.

Handler handler = new Handler();
new Thread() {
    @Override public void run() {
        // ... setup the movie (using the code from above)
        // ... create and display the custom view, passing the movie

        while(!Thread.currentThread().isInterrupted()) {
            handler.post(new Runnable() {
                public void run(){
                    view.invalidate();
                }
            });
            try {
                Thread.sleep(50); // yields 20 fps
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}.start();

有一个非常好的解决办法有各种甜的进度条和错误检查,但核心是在这里。

A really nice solution would have all sorts of sweet progress bars and error checking, but the core is here.