Pregunta

Supongamos que tengo la URL para un gran gif animado y quiero hacer una actividad similar a YouTube que muestre la animación de forma continua. ¿Cómo puedo

  1. transmitir en la imagen?
  2. ¿hacer que se muestre con animación real?

Sé que ImageView no es la respuesta, ya que solo muestra el primer fotograma.

Una ventaja sería tener acceso a su estado de almacenamiento en búfer para que yo también pueda sincronizar la transmisión de sonido, esto es parte de un YTMND aplicación de visor. Si bien podría crear un servicio que transcodifique los archivos gif públicos en un formato más agradable, me gustaría que la aplicación funcione sin dependencias adicionales.

¿Fue útil?

Solución

El bosquejo general de la solución es utilizar el uso personalizado de View que dibuja pide una Movie para dibujar periódicamente en el Canvas .

El primer paso es construir la instancia de Movie . Existe una fábrica llamada decodeStream que puede hacer que una película tenga un InputStream pero no es suficiente usar la transmisión desde una UrlConnection . Si intenta esto, obtendrá una IOException cuando el cargador de películas intente llamar a reset en la transmisión. El truco, por desafortunado que sea, es usar un BufferedInputStream separado con una mark configurada manualmente para decirle que guarde suficientes datos que reset No fallará. Afortunadamente, la URLConnection puede decirnos cuántos datos esperar. Digo que este truco es desafortunado porque efectivamente requiere que toda la imagen esté almacenada en la memoria (lo cual no es un problema para las aplicaciones de escritorio, pero es un problema grave en un dispositivo móvil con memoria limitada).

Aquí hay un fragmento del código de configuración de 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();

A continuación, debe crear una vista que muestre esta Película . Una subclase de View con un onDraw personalizado hará el truco (suponiendo que tenga acceso a la Movie que creó con el código anterior).

@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 no se activará para volverse a dibujar sin ayuda, y llamar ciegamente a invalidate () al final de onDraw es solo un desperdicio de energía. En otro hilo (probablemente el que usó para descargar los datos de la imagen), puede publicar mensajes en el hilo principal, solicitando que la vista se invalide a un ritmo constante (pero no loco).

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 solución realmente buena tendría todo tipo de dulces barras de progreso y verificación de errores, pero el núcleo está aquí.

Otros consejos

¿Intentaste BitmapDecode?

Hay un ejemplo en las Demos API aquí .

Glide demuestran la manera más fácil y eficiente de lograr esto con solo una línea de código: -

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

El resultado está aquí: -

 ingrese la descripción de la imagen aquí

Gif tomado de aquí http://giphy.com/search/big-gif/3

Agregue jar desde aquí: - https://github.com/bumptech/glide/releases

¿Quizás AnimationDrawable podría funcionar para usted? EDITAR: no si desea cargar desde una URL como esta publicación. Lo siento

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

Dependiendo de la complejidad del GIF, es decir, si se trata de un simple indicador de carga / progreso, podría separar el GIF, guardar cada imagen por separado y usar AnimationDrawable del Marco de Android.

Para barras de progreso simples, esto puede ser menos propenso a errores, tal vez incluso más eficiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top