2012-02-23 20 views
8

Necesito reemplazar frases de texto en a con imágenes y luego anexarlas a un TextView. Para los Dratables normales esto no es problema, pero cuando el Drawable es un Dibujo de Animación, no sé dónde ni cuándo llamar al .start();.Cargue dinámicamente una AnimationDrawable en un TextView

Éste es cómo añadir texto a la Vista de Texto:

textview.append(Html.fromHtml(textWithHtmlImgTags, imagegetter, null)); 

Las etiquetas de imagen en los textWithHtmlImgTags se reemplacen con imagegetter:

new ImageGetter() 
{ 
    @Override 
    public Drawable getDrawable(String source) { 

     if(source.endsWith("_ani")) 
     { 
      Log.i("cmv", "This is an animated drawable."); 

      AnimationDrawable dra = (AnimationDrawable)res.getDrawable(sRes.get(source)); 
      dra.setBounds(0, 0, dra.getIntrinsicWidth(), dra.getIntrinsicHeight()); 
      dra.start(); // This doesn't work.. 

      return dra; 
     } 

     Drawable dr = res.getDrawable(sRes.get(source)); 
     dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight()); 
     return dr; 
    } 

}; 

se añaden Mis AnimationDrawables, pero no están animados (Están atrapados en el cuadro 1).

En la documentación que dice:

Es importante tener en cuenta que el método start() llamada en la AnimationDrawable no se puede llamar durante el método onCreate() de su actividad, ya que la AnimationDrawable todavía no está totalmente unido a la ventana. Si desea reproducir la animación de inmediato, sin necesidad de interacción, entonces puede llamar desde el método onWindowFocusChanged() en su actividad, que se llamará cuando Android enfoque su ventana.

Dado que las imágenes se agregan dinámicamente, no creo que tenga nada que ver con onCreate(). Supongo que llamo a mi .start() cuando mi dibuja is not yet fully attached to the window, pero dónde/cuándo/cómo debería ¿Lo llamo?

¡Gracias de antemano!

+0

después de establecer la llamada drawbales 'textView.bringToFront()' y luego llamar a '.start()' para animar .. – MKJParekh

Respuesta

6

me salió con la solución. En su TextView personalizado:

(1) Primero, debe decidir el momento del inicio y la detención de la animación.

@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 

    handleAnimationDrawable(true); 
} 

@Override 
protected void onDetachedFromWindow() { 
    super.onDetachedFromWindow(); 

    handleAnimationDrawable(false); 
} 

private void handleAnimationDrawable(boolean isPlay) { 
    CharSequence text = getText(); 
    if (text instanceof Spanned) { 
     Spanned span = (Spanned) text; 
     ImageSpan[] spans = span.getSpans(0, span.length() - 1, 
       ImageSpan.class); 
     for (ImageSpan s : spans) { 
      Drawable d = s.getDrawable(); 
      if (d instanceof AnimationDrawable) { 
       AnimationDrawable animationDrawable = (AnimationDrawable) d; 
       if (isPlay) { 
        animationDrawable.setCallback(this); 
        animationDrawable.start(); 
       } else { 
        animationDrawable.stop(); 
        animationDrawable.setCallback(null); 
       } 
      } 
     } 
    } 
} 

(2) Y luego implemente su propio Drawable.Callback para activar el redibujado.

@Override 
public void invalidateDrawable(Drawable dr) { 
    invalidate(); 
} 

@Override 
public void scheduleDrawable(Drawable who, Runnable what, long when) { 
    if (who != null && what != null) { 
     mHandler.postAtTime(what, when); 
    } 
} 

@Override 
public void unscheduleDrawable(Drawable who, Runnable what) { 
    if (who != null && what != null) { 
     mHandler.removeCallbacks(what); 
    } 
} 
+0

¡Genial! Esto es exactamente lo que necesitaba! –

1

Supongo que la pregunta importante es: ¿cuándo haces la llamada?

textview.append(Html.fromHtml(textWithHtmlImgTags... 

Si está llamando a esto después de onCreate, puede llamar al animation.start(). Si se invoca en el método Crear(), yo:

  • guardo la lista de los generadores generados en ImageGetter;
  • inicio de la llamada() en todos los dibujables en onAttachedToWindow o onStart (no estoy seguro si trabajan en la función onStart)
+0

Realizo la llamada varias veces, la primera llamada está en onCreate. Después de eso se llama varias veces más (cada vez que la aplicación recibe una respuesta de un servidor). Traté de mantener una lista de todas las AnimationDrawables e iniciarlas en AttachedToWindow, pero aún permanecen bloqueadas en el primer fotograma. –

1

Vista ya implementa Drawable.Callback lo que sólo necesita la siguiente TextView anula para mostrar objetos en un AnimationDrawable ImageSpan:

// comparing against drawables found in the spans is probably safer 
@Override 
protected boolean verifyDrawable(Drawable who) { 
    return (super.verifyDrawable(who) || who instanceof AnimationDrawable); 
} 

// again comparing against drawables found in the spans is probably safer 
@Override 
public void invalidateDrawable(Drawable drawable) { 
    if (drawable instanceof AnimationDrawable) { 
     onLayout(true, getLeft(), getTop(), getRight(), getBottom()); 
     invalidate(); 
     return; 
    } 
    super.invalidateDrawable(drawable); 
} 

Anulación verifyDrawable es necesario para que las implementaciones de la superclase Disponibles.La devolución de llamada aceptará objetos Drawable inesperados y gestionará la programación.

Llamar a OnLayout obliga al TextView a invalidar su lista de visualización en caché, de lo contrario, los marcos actualizados no se dibujan.

También encontré que, por algún motivo, si creaba ImageSpan en referencia al ID del recurso de animación, el recurso no se almacenaba en la memoria caché y parecía volver a cargarse cada vez que se llamaba a ImageSpan.getDrawable(). Al cargar el recurso, establecer sus límites y pasarlo al constructor de ImageSpan evité ese problema.

use onAttachedToWindow/onDetachedFromWindow como se sugiere.

Cuestiones relacionadas