Frage

Angenommen, ich die URL für große animierte gif haben und ich wollte einen youtube ähnliche Aktivität machen, die die Animation in einem Streaming-Weg zeigt. Wie kann ich

  1. Strom in dem Bild?
  2. get es tut Display mit tatsächlichen Animation?

Ich weiß ImageView nicht die Antwort ist, da es nur das erste Bild zeigt.

Ein Bonus würde den Zugang zu seinem Pufferstatus wird mit so kann ich auch Streaming-Sound synchronisieren - dieser Teil einer YTMND Viewer-Anwendung. Während ich einen Dienst schaffen könnte, die die öffentlichen GIF-Dateien in ein schöneres Format transkodiert, würde ich die App ohne zusätzliche Abhängigkeiten funktionieren mag.

War es hilfreich?

Lösung

Die allgemeine Skizze der Lösung beschäftigen benutzerdefinierte View verwenden, die eine Movie fragt zeichnet sich periodisch auf den Canvas zu ziehen.

Der erste Schritt baut die Movie Instanz. Es ist ab Werk decodeStream genannt, die einen Film ein InputStream gegeben machen können, aber es ist nicht genug, um den Strom von einem UrlConnection zu verwenden. Wenn Sie dies versuchen, erhalten Sie eine IOException erhalten, wenn der Film loader reset auf dem Stream zu nennen versucht. Der Hack, unglücklich, wie es ist, ist eine getrennte BufferedInputStream mit einem verwenden manuell eingestellt mark es zu sagen, genug Daten zu speichern, die nicht scheitern reset. Glücklicherweise kann die URLConnection uns sagen, wie viele Daten zu erwarten. Ich sage das Hack ist bedauerlich, weil es effektiv das gesamte Bild erfordert im Speicher gepuffert wird (was kein Problem für Desktop-Anwendungen, aber es ist ein ernstes Problem auf einem Speicher-constrained mobilen Gerät).

Hier ist ein Schnipsel des 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();

Als nächstes müssen Sie eine Ansicht erstellen, die diese Movie angezeigt wird. Eine Unterklasse von View mit einem benutzerdefinierten onDraw den Trick (vorausgesetzt, es Zugang zum Movie hat Sie mit dem vorherigen Code erstellt).

@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);
    }
}

Die Ansicht wird nicht selbst auslösen, ohne Hilfe neu gezeichnet werden, und blind Aufruf invalidate() am Ende onDraw ist nur eine Energieverschwendung. In einem anderen Thread (wahrscheinlich diejenige, die Sie die Bilddaten zum Download verwendet wird), Sie können Nachrichten auf den Haupt-Thread, für die Ansicht zu fragen bei einem konstanten (aber nicht verrückt) Schritt für ungültig erklärt werden.

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

Eine wirklich schöne Lösung wäre, alle Arten von süßen Fortschrittsbalken und Fehlerprüfung, aber der Kern ist hier.

Andere Tipps

Haben Sie versucht, BitmapDecode?

Es gibt ein Beispiel in den API-Demos hier .

Glide beweist einfachste und effizienteste Weg, dies zu erreichen, mit nur eine Zeile Code: -

Glide.with(getApplicationContext())
            .load(Uri.parse("https://media1.giphy.com/media/5ziaphcUWGKPu/200.gif"))
            .asGif().placeholder(R.drawable.ic_launcher).crossFade()
            .into(imageView);

Das Ergebnis ist hier: -

Gif von hier genommen http://giphy.com/search/big-gif/3

In jar von hier: - https://github.com/bumptech/glide/releases

Vielleicht AnimationDrawable könnte für Sie arbeiten? EDIT: Nicht, wenn Sie von einer URL geladen werden sollen, wie dieser Beitrag über ist. Es tut uns Leid

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

Je nach Komplexität des GIF das heißt, wenn es eine einfache Laden / Fortschrittsanzeige ist, dass Sie das GIF auseinander brechen könnten, jedes Bild speichern separat und verwenden Sie den AnimationDrawable Android-Framework.

Für die einfachen Fortschrittsbalken kann dies weniger fehleranfällig, vielleicht sogar mehr performant.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top