Question

Supposons que j'ai l'URL d'un grand gif animé et que je souhaite créer une activité similaire à YouTube, qui affiche l'animation sous forme de diffusion en continu. Comment puis-je

  1. diffuser dans l'image?
  2. l'obtenir afficher avec l'animation réelle?

Je sais que ImageView n’est pas la solution, il n’affiche que la première image.

Un bonus aurait accès à son statut de mise en mémoire tampon afin que je puisse également synchroniser le son en streaming - cela fait partie d'un YTMND application de visualisation. Bien que je puisse créer un service qui transcodera les fichiers gif publics dans un format plus agréable, j'aimerais que l'application fonctionne sans dépendances supplémentaires.

Était-ce utile?

La solution

L'esquisse générale de la solution consiste à utiliser un View personnalisé qui dessine demande à un Film de se dessiner périodiquement dans le Canvas .

La première étape consiste à créer l'instance Movie . Il existe une usine appelée decodeStream qui peut créer un film avec un InputStream , mais il ne suffit pas d'utiliser le flux à partir d'un UrlConnection . Si vous essayez ceci, vous obtiendrez une IOException lorsque le chargeur de films essaie d'appeler reset sur le flux. Le hack, malheureusement, consiste à utiliser un BufferedInputStream séparé avec une marque définie manuellement pour lui dire de sauvegarder suffisamment de données pour que reset n'échouera pas. Heureusement, URLConnection peut nous indiquer le volume de données à attendre. Je dis que ce hack est regrettable car il nécessite en réalité que l’ensemble de l’image soit mise en tampon dans la mémoire (ce n’est pas un problème pour les applications de bureau, mais c’est un problème grave pour un appareil mobile à mémoire limitée).

Voici un extrait du code d'installation Film :

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

Ensuite, vous devez créer une vue qui affichera ce Film . Une sous-classe de View avec un onDraw personnalisé fera l'affaire (en supposant qu'elle ait accès au Film que vous avez créé avec le code précédent).

@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 vue ne se déclenchera pas sans aide et l'appel aveugle de invalidate () à la fin de onDraw n'est qu'un gaspillage d'énergie. Dans un autre fil (probablement celui que vous avez utilisé pour télécharger les données d'image), vous pouvez envoyer des messages au fil principal, demandant que la vue soit invalidée à un rythme soutenu (mais pas fou).

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

Une très bonne solution aurait toutes sortes de jolies barres de progression et de vérification des erreurs, mais le coeur est ici.

Autres conseils

Avez-vous essayé BitmapDecode ?

Il existe un exemple dans les démonstrations d'API ici .

Glide est le moyen le plus simple et le plus efficace de réaliser cela simplement une ligne de code: -

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

Le résultat est ici: -

 entrer la description de l'image ici

Gif tiré d'ici http://giphy.com/search/big-gif/3

Ajoutez le fichier JAR à partir de cet emplacement: - https://github.com/bumptech/glide/releases

Peut-être que AnimationDrawable pourrait fonctionner pour vous? EDIT: Pas si vous voulez charger depuis une URL comme celle-ci. Désolé

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

En fonction de la complexité du fichier GIF, c’est-à-dire s’il s’agit d’un simple indicateur de chargement / progression, vous pouvez le séparer, enregistrer chaque image séparément et utiliser AnimationDrawable du Framework Android.

Pour les barres de progression simples, cela peut être moins sujet aux erreurs, voire plus performant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top