Android:如何显示给定网址的大型动画gif?
-
03-07-2019 - |
题
假设我有大型动画gif的URL,我想创建一个类似youtube的活动,以流式方式显示动画。我如何
- 图片中的流?
- 用实际动画显示它吗? 醇>
我知道 ImageView
不是答案,因为它只显示第一帧。
奖励可以访问其缓冲状态,因此我也可以同步流声音 - 这是 YTMND <的一部分/ a>查看器应用程序。虽然我可以创建一个将公共gif文件转码为更好格式的服务,但我希望该应用程序能够在没有其他依赖项的情况下运行。
解决方案
解决方案的一般草图是使用自定义 View
,它会绘制一个 Movie
,定期将自己绘制到 Canvas
。
第一步是构建 Movie
实例。有一个名为 decodeStream
的工厂可以使用 InputStream
制作电影,但仅使用来自 UrlConnection
的流是不够的。如果您尝试这样做,当电影加载器尝试在流上调用 reset
时,您将获得 IOException
。黑客,不幸的是,使用一个单独的 BufferedInputStream
和一个手动设置的标记
来告诉它保存足够的数据 reset
不会失败。幸运的是, URLConnection
可以告诉我们预期会有多少数据。我说这个hack是不幸的,因为它实际上需要将整个映像缓存在内存中(对于桌面应用来说这不是问题,但在内存受限的移动设备上这是一个严重的问题)。
以下是 Movie
设置代码的片段:
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();
接下来,您需要创建一个显示此 Movie
的视图。带有自定义 onDraw
的 View
的子类将完成这一操作(假设它可以访问您使用前面的代码创建的 Movie
)。 / p>
@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
的末尾盲目地调用 invalidate()
只是一种能量浪费。在另一个线程(可能是您用来下载图像数据的线程)中,您可以将消息发布到主线程,要求视图以稳定(但不是疯狂)的速度失效。
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();
一个非常好的解决方案会有各种各样的甜蜜进度条和错误检查,但核心就在这里。
其他提示
您是否尝试过 BitmapDecode
?
API演示中有一个示例此处。
Glide 证明了最简单有效的方法一行代码: -
Glide.with(getApplicationContext())
.load(Uri.parse("https://media1.giphy.com/media/5ziaphcUWGKPu/200.gif"))
.asGif().placeholder(R.drawable.ic_launcher).crossFade()
.into(imageView);
结果在这里: -
从这里采取的GIF http://giphy.com/search/big-gif/3
从这里添加jar: - https://github.com/bumptech/glide/releases一>
也许 AnimationDrawable 可能适合您?编辑:如果你想从这个帖子的URL加载,不是。遗憾
http://developer.android.com/reference/android/图形/抽拉/ AnimationDrawable.html
根据GIF的复杂程度,即如果它是一个简单的加载/进度指示器,您可以将GIF分开,单独保存每个图像并使用Android Framework的AnimationDrawable。
对于简单的进度条,这可能不易出错,甚至可能更高效。