15

大きなアニメーション gif の URL があり、ストリーミング方法でアニメーションを表示する youtube のようなアクティビティを作成したいとします。どうすれば

  1. 画像に流れますか?
  2. 実際のアニメーションで表示しますか?

ImageView最初のフレームしか表示されないため、答えではない ことはわかっています。

おまけとして、バッファリング ステータスにアクセスできるので、ストリーミング サウンドも同期できます。これはYTMNDビューアー アプリケーションの一部です。パブリック gif ファイルをより適切な形式にトランスコードするサービスを作成することもできますが、追加の依存関係なしでアプリが機能することを望みます。

4

4 に答える 4

12

解決策の一般的なスケッチは、定期的に描画Viewするように要求するカスタムを使用することです。MovieCanvas

最初のステップは、Movieインスタンスを構築することです。decodeStream与えられた映画を作ることができると呼ばれる工場がありますがInputStream、からのストリームを使用するのに十分ではありませんUrlConnection。これを試してみるとIOException、ムービーローダーresetがストリームを呼び出そうとしたときに取得できます。ハックは、残念ながらBufferedInputStream、手動で設定されたセパレートを使用して、失敗しないmark十分なデータを保存するように指示することです。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();

次に、これを表示するビューを作成する必要がありますMovieViewカスタムのサブクラスはonDrawトリックを実行します(前のコードで作成したにアクセスできると仮定し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);
    }
}

invalidate()ビューは、助けなしに再描画されることはありません。最後に盲目的に呼び出すことonDrawは、エネルギーの浪費にすぎません。別のスレッド(おそらく画像データのダウンロードに使用したスレッド)では、メインスレッドにメッセージを投稿して、ビューを一定の(ただし異常ではない)ペースで無効にするように要求できます。

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();

本当に素晴らしいソリューションには、あらゆる種類の甘いプログレスバーとエラーチェックがありますが、コアはここにあります。

于 2009-05-05T06:47:29.087 に答える
1

やってみましたBitmapDecodeか?

ここ にAPIデモの例があります。

于 2009-05-02T15:38:15.403 に答える
1

Glideは、たった 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

于 2015-12-02T19:55:01.030 に答える
0

多分AnimationDrawableがあなたのために働くことができますか? 編集: この投稿のように URL からロードしたい場合はそうではありません。ごめん

http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

GIF の複雑さに応じて、つまり単純な読み込み/進行状況インジケーターの場合は、GIF を分割し、各画像を個別に保存して、Android フレームワークの AnimationDrawable を使用できます。

単純な進行状況バーの場合、これによりエラーが発生しにくくなり、パフォーマンスがさらに向上する可能性があります。

于 2011-07-10T15:10:07.757 に答える