Android:URLを指定して大きなアニメーションGIFを表示するにはどうすればよいですか?
-
03-07-2019 - |
質問
大きなアニメーションgifのURLがあり、アニメーションをストリーミング表示するYouTubeのようなアクティビティを作成したいとします。方法
- 画像内のストリーム
- 実際のアニメーションで表示しますか?
ImageView
は最初のフレームのみを表示するため、答えではありません。
ボーナスはバッファリングステータスにアクセスできるため、ストリーミングサウンドも同期できます-これは YTMND ビューアアプリケーション。パブリックgifファイルをより良い形式にトランスコードするサービスを作成できましたが、追加の依存関係なしにアプリが機能することを望みます。
解決
ソリューションの一般的なスケッチは、カスタム View
を使用して、定期的に Canvas
に自分自身を描画する Movie
を要求することです。
最初のステップは、 Movie
インスタンスを構築することです。 decodeStream
と呼ばれるファクトリーがあり、 InputStream
を指定してムービーを作成できますが、 UrlConnection
からのストリームを使用するだけでは不十分です。これを試みると、ムービーローダーがストリームで reset
を呼び出そうとしたときに IOException
が返されます。残念ながら、ハッキングは、手動で設定された mark
で区切られた BufferedInputStream
を使用して、 reset
失敗しません。幸いなことに、 URLConnection
は、予想されるデータ量を示すことができます。このハックは、画像全体をメモリにバッファリングする必要があるため、残念です(デスクトップアプリでは問題ありませんが、メモリに制約のあるモバイルデバイスでは深刻な問題です)。
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
にアクセスできると仮定します)。
@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デモに例がありますこちら。
グライド は、これを実現する最も簡単で効率的な方法を証明します。 1行のコード:-
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/ graphics / drawable / AnimationDrawable.html
GIFの複雑さに依存します。つまり、単純な読み込み/進行インジケータの場合は、GIFを分解し、各画像を個別に保存し、AndroidフレームワークのAnimationDrawableを使用します。
シンプルなプログレスバーの場合、これはエラーが少なくなり、パフォーマンスが向上する可能性があります。