Domanda

Supponiamo di avere l'URL per una grande gif animata e che volessi creare un'attività simile a quella di YouTube che visualizzi l'animazione in modo streaming. Come posso

  1. stream nell'immagine?
  2. farlo visualizzare con un'animazione reale?

So che ImageView non è la risposta in quanto mostra solo il primo fotogramma.

Un bonus avrebbe accesso al suo stato di buffering in modo da poter sincronizzare anche l'audio in streaming - questo fa parte di un YTMND applicazione visualizzatore. Mentre potrei creare un servizio che transcodifichi i file gif pubblici in un formato migliore, vorrei che l'app funzionasse senza dipendenze aggiuntive.

È stato utile?

Soluzione

Lo schizzo generale della soluzione è utilizzare impiegare View personalizzato che disegna chiede a un Movie di attingere periodicamente al Canvas .

Il primo passo è la creazione dell'istanza Movie . Esiste una fabbrica chiamata decodeStream che può creare un film con un InputStream ma non è sufficiente usare lo stream da un UrlConnection . Se provi questo, otterrai un IOException quando il caricatore di film tenta di chiamare reset sullo stream. L'hack, per quanto sfortunato, è usare un BufferedInputStream separato con un mark impostato manualmente per dirgli di salvare abbastanza dati che ripristina non fallirà. Fortunatamente, URLConnection può dirci quanti dati aspettarci. Dico che questo hack è sfortunato perché richiede effettivamente che l'intera immagine sia bufferizzata in memoria (il che non è un problema per le app desktop, ma è un problema serio su un dispositivo mobile con memoria limitata).

Ecco un'istantanea del codice di installazione 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();

Successivamente, è necessario creare una vista che visualizzi questo film . Una sottoclasse di Visualizza con un onDraw personalizzato farà il trucco (supponendo che abbia accesso al Movie che hai creato con il codice precedente).

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

La vista non si attiverà per essere ridisegnata senza aiuto e chiamare alla cieca invalidate () alla fine di onDraw è solo uno spreco di energia. In un altro thread (probabilmente quello che hai usato per scaricare i dati dell'immagine), puoi pubblicare messaggi nel thread principale, chiedendo che la vista venga invalidata a un ritmo costante (ma non folle).

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

Una soluzione davvero piacevole avrebbe tutti i tipi di dolci barre di avanzamento e controllo degli errori, ma il nucleo è qui.

Altri suggerimenti

Hai provato BitmapDecode?

C'è un esempio nelle demo API qui .

Glide si dimostrano il modo più semplice ed efficiente per raggiungere questo obiettivo con solo una riga di codice: -

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

Il risultato è qui: -

 inserisci qui la descrizione dell'immagine

GIF tratte da qui http://giphy.com/search/big-gif/3

Aggiungi jar da qui: - https://github.com/bumptech/glide/releases

Forse AnimationDrawable potrebbe funzionare per te? EDIT: Non se si desidera caricare da un URL come questo post riguarda. Siamo spiacenti

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

A seconda della complessità della GIF, ovvero se si tratta di un semplice indicatore di caricamento / avanzamento, è possibile dividere la GIF, salvare ogni immagine separatamente e utilizzare AnimationDrawable di Android Framework.

Per semplici barre di avanzamento questo potrebbe essere meno soggetto a errori, forse anche più performante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top