2011-04-10 17 views
13

Tengo una serie de imágenes fijas y un total de más de 500 imágenes presentadas en un directorio dibujable. Necesito hacer una animación (cargar aproximadamente 20 imágenes por segundo). Quiero que funcione sin problemas y sin Excepción de falta de memoria.Android: hacer animación a partir de imágenes estáticas

Tengo la idea de hacer esto para que las imágenes de 2 a 3 segundos (40 a 60 imágenes) se carguen en la memoria y se muestren y luego se eliminen (suelten la memoria) y luego las imágenes de los próximos 2 a 3 segundos debería cargar Esta técnica puede prevenir la excepción de falta de memoria. Es solo una idea, no sé si es una buena idea o no. Por favor, guíame una idea mejor con un código para ir ... Si mi idea es mucho mejor y puede funcionar, por favor dígame un código de ayuda para hacer eso.

Después de leer las respuestas y hacer como usted sugiere, he escrito algo de código como esto:

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:id="@+id/llMain"> 

<ViewFlipper android:id="@+id/imageflipper" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 
<ImageView android:id="@+id/ImageView01" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"   
     android:scaleType="centerInside"   
     android:layout_gravity="center" /> 
    </ViewFlipper> 
    </LinearLayout> 

y aquí está mi código para hacer la animación:

public class Animation extends Activity { 
ViewFlipper flipper; 
int myIndex = 216; 
private final Handler handler = new Handler(); 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    flipper=(ViewFlipper)findViewById(R.id.imageflipper); 
    doTheAutoRefresh(); 
     //displayData(); 
} 

private void doTheAutoRefresh() { 
    handler.postDelayed(new Runnable() { 
     public void run(){ 
      displayData(); // this is where you put your refresh code 
      doTheAutoRefresh(); 
      } 
     }, 30); 

} 

private void displayData() 
{ 
    Resources r = getResources(); 
    if(myIndex > 230){ 
     myIndex = 216; 
     ImageView myImg = (ImageView)findViewById(R.id.ImageView01); 
     myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation")); 

     myIndex += 1; 
     flipper.showNext(); 
    } 
    else{ 
     ImageView myImg = (ImageView)findViewById(R.id.ImageView01); 

     myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation")); 

     myIndex += 1; 
     flipper.showNext(); 
    } 
} 

}

pero es muy lento Configuré el tiempo de actualización en 30 milisegundos, pero en realidad no está refrescando demasiado rápido, sino que su tiempo de actualización es de aproximadamente 1 segundo. ¿Alguna sugerencia para que sea rápido sentir como una verdadera animación?

Gracias,

Respuesta

18

OK. El mayor problema y la solución más fácil que tuve después de tantos días. Nunca esperaría que fuera tan fácil de hacer ...: D

He usado tanto el controlador como el temporizador para lograr con solo una vista de imagen, sin flipper, sin animación nada más ... Aquí es mi solución:

----- main.archivo XML -----

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:background="@drawable/background"> 

<ImageView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/imageView1"> 
</ImageView> 

Y aquí es la manera que lo he hecho:

public class MainActivity extends Activity { 
private ImageView _imagView; 
private Timer _timer; 
private int _index; 
private MyHandler handler; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    handler= new MyHandler(); 
    _imagView=(ImageView) findViewById(R.id.imageView1); 

    _index=0; 
    _timer= new Timer(); 
    _timer.schedule(new TickClass(), 500, 200); 
} 

private class TickClass extends TimerTask 
{ 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     handler.sendEmptyMessage(_index); 
     _index++; 
    } 
} 

private class MyHandler extends Handler 
{ 
    @Override 
    public void handleMessage(Message msg) { 
     // TODO Auto-generated method stub 
     super.handleMessage(msg); 

     try { 
       Bitmap bmp= BitmapFactory.decodeStream(MainActivity.this.getAssets().open("drum_"+_index+".png")); 
       _imagView.setImageBitmap(bmp); 

       Log.v("Loaing Image: ",_index+""); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.v("Exception in Handler ",e.getMessage()); 
     } 
    } 
} 

}

Nota: he puesto todo mi imágenes al directorio de activos.

Es tan simple como puede, nada grande para hacer ...

espero que va a ser útil para alguien que quiera ir como esto :)

+0

@Mudasser Hassan si todas las imágenes en el lado del servidor y tengo que descargar todas las imágenes y hacer ese tipo de trabajo. (Reproducción de un video o animación de imágenes). ¿Cómo puedo hacer eso? Necesito que todas las imágenes muestren como 360 grados rotando una sola imagen. Como ese http://www.mathieusavard.info/threesixty/demo.html –

+0

Gracias. Si todas las imágenes son del servidor y tenemos que descargar todas las imágenes y mostrar. ¿Has dado alguna idea? Estoy enfrentando un problema con eso. Por favor ayuda. –

+0

Si usó 'Handler.post()' el código sería más corto. Otra cuestión es que decodifique la imagen en el hilo de UI, eso no es bueno.Una solución más elegante sería decodificar la siguiente imagen en segundo plano (usando 'AsyncTask') con anticipación y mostrarla después de 200 ms o después de que la imagen haya sido decodificada, si lleva más tiempo. – Mixaz

2

Cargando varias imágenes es muy caro.

Creo que es mejor cargar una sola imagen que contenga todos los movimientos de esa cierta animación. Una tira de animación.

private Bitmap animation = BitmapFactory.decodeResource(getResources(), R.drawable.myPng);

La idea es recorrer el mapa de bits.

+0

Sprite no es mi caso. Te dije que tengo más de 500 imágenes. Primero, no puedo hacer una tira de 500 imágenes, si lo hago, creo que no será posible cargar esa tira ENORME o no será un buen enfoque ... Buscando una mejor idea ... –

1

Bueno, estoy usando viewFlipper, cambiando de vista. Lo bueno de esto es que u puede ver imagen anterior se deslice fuera mientras que el nuevo se desliza en

imagen Dentro método de visualización:.

if (direction == NEXT) { 
     viewFlipper.setInAnimation(slideLeftIn); 
     viewFlipper.setOutAnimation(slideLeftOut); 

     if (currImg < max) 
      currImg++; 
     if (currImg == max) 
      currImg = 0; 

     if (currentView == 0) { 
      currentView = 1; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView02); 
      iv.setImageResource(images[currImg]); 
     } else if (currentView == 1) { 
      currentView = 2; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView03); 
      iv.setImageResource(images[currImg]); 
     } else { 
      currentView = 0; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView01); 
      iv.setImageResource(images[currImg]); 
     } 
     viewFlipper.showNext(); 
    } 
    else if (direction == PREV) { 
     viewFlipper.setInAnimation(slideRightIn); 
     viewFlipper.setOutAnimation(slideRightOut); 

     if (currImg > 0) 
      currImg--; 
     else if (currImg <= 0) 
      currImg = (max-1); 

     if (currentView == 0) { 
      currentView = 2; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView03); 
      iv.setImageResource(images[currImg]); 
     } else if (currentView == 2) { 
      currentView = 1; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView02); 
      iv.setImageResource(images[currImg]); 
     } else { 
      currentView = 0; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView01); 
      iv.setImageResource(images[currImg]); 
     } 
     viewFlipper.showPrevious(); 

Y en el interior archivo XML:

 <ViewFlipper android:id="@+id/imageflipper" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" > 

     <ImageView android:id="@+id/ImageView01" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     <ImageView android:id="@+id/ImageView02" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     <ImageView android:id="@+id/ImageView03" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     </ViewFlipper> 
+0

todavía hay 2 cosas Estoy confundido. Primero, ¿dónde está el código de reciclaje? ¿Cómo estás reciclando las imágenes antiguas y cargando las nuevas? Segundo, quiero hacer una animación, no voltear las imágenes hacia la izquierda o hacia la derecha, animación suave (carga de nuevas imágenes y descarga de imágenes antiguas automáticamente) ... Soy nuevo en Android, y tampoco sé mucho sobre JAVA. Cualquier ejemplo de código será realmente útil y apreciado ... :) –

+0

Bueno, Java tiene un recolector de basura, por lo que no tiene que liberar manualmente la memoria como en obj-c para iphone, etc. Puede usar system.gc() para forzar iniciar el recolector de basura. Iv.setImageResource() está cambiando la imagen en la vista de imagen y declaro 2 animaciones (para imágenes antiguas y nuevas) que se utilizarán para animar el cambio. Si desea la animación automática en su lugar, solo agregue algunos temporizadores y utilice el método anterior como cada 2 segundos o smth. Ofc, declara animaciones de xml y conserva el valor de la dirección (en mi caso necesitaba NEXT o PREV). – yosh

+0

He hecho algo al leer su código y también después de explorar más en otras publicaciones/sitios. Edité mi pregunta y agregué mi código a ella. Su refrescante es demasiado lento. Quiero que sea muy rápido para sentirme como una verdadera animación. ¿Cualquier sugerencia? Gracias –

30

Uso un FrameAnimation, por ejemplo, en res/drawable/movie.xml:

<?xml version="1.0" encoding="utf-8"?> 
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" 
    android:oneshot="true"> 
    <item android:drawable="@drawable/frame1" android:duration="50" /> 
    <item android:drawable="@drawable/frame2" android:duration="50" /> 
    <item android:drawable="@drawable/frame3" android:duration="50" /> 
    etc... 
</animation-list> 

Y luego, en Java:

imageView.setBackgroundResource(R.drawable.movie); 
AnimationDrawable anim = (AnimationDrawable) imageView.getBackground(); 
anim.start(); 
+1

¿Funcionará para 500 imágenes sin OutOfMemoryException? ¿Llamará a gc() después de dibujar cada imagen? y qué tipo de cosas de pausa/reanudar/detener/reproducir? ¿Puedo hacer estas funciones con este enfoque? –

+0

No lo he intentado con tantas imágenes, pero es manejado por el framework de Android, por lo que se supone que es inteligente. Estoy bastante seguro de que maneja la memoria muy bien. Dicho esto, tal vez no sea adecuado para un video completo ... ¿Por qué no conviertes tus imágenes en un video, lo pones en res/raw y luego lo reproduces con MediaPlayer? Es muy fácil, además tiene pausa, jugar, buscar y todo eso. Y la compresión será mejor, posiblemente mucho mejor ... – olivierg

+0

muchas gracias. El video no resolverá mi problema, creo que estoy tratando de desarrollar alguna aplicación como Talking Santa. Puede consultarlo aquí [enlace] (http://www.appbrain.com/app/talking-santa-free/com.outfit7.talkingsantafree) –

Cuestiones relacionadas