Android: Wie kann eine Anzeige eine große animierte gif eine URL gegeben?
-
03-07-2019 - |
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
- Strom in dem Bild?
- 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.
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.