Воспроизведение больших кадров PNG-анимации в Android с animationDrawable - PullRequest
4 голосов
/ 28 декабря 2010

У меня есть приложение с кнопками, которые при нажатии воспроизводят различные покадровые анимации. Анимации хранятся в виде последовательности файлов .png. Некоторые из анимаций занимают небольшую область, и они, кажется, прекрасно играют, используя animationDrawable. Однако некоторые анимации занимают большую часть экрана (даже если они в основном прозрачные с использованием альфа-канала), и я получаю сообщение об ошибке нехватки памяти, когда приложение загружается на мой телефон (но не эмулятор). Я не могу воспроизвести их как видеофайлы, потому что они должны перекрывать главный экран.

Мой главный вопрос - есть ли способ проигрывать большие анимации последовательности png (скажем, 60 кадров при 320x480), используя animationDrawable?

До сих пор в моем исследовании, похоже, не было никакого способа обойти ограничения памяти ... поэтому я искал свой собственный метод, который создает ImageView и заполняет его растровым изображением, а затем последовательно заменяет растровое изображение с каждым кадром после задержки. Однако с помощью этой техники моя анимация воспроизводит только первый и последний кадры.

Вот код моего удара при использовании animationDrawable - «шимпанзе» играет нормально, но когда я добавляю «пузыри» (большие изображения), приложение вообще не загружается - logCat показывает: «ОШИБКА / dalvikvm-heap (3248): внешнее выделение 1008000 байт слишком велико для этого процесса ... ОШИБКА / AndroidRuntime (3248): java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины «

public class Babymode_tst extends Activity implements OnClickListener{
 /** Called when the activity is first created. */
 AnimationDrawable chimpAnimation;
 AnimationDrawable bubblesAnimation;
 private MediaPlayer mp;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  setVolumeControlStream(AudioManager.STREAM_MUSIC);

  final ImageButton chimpButton = (ImageButton) findViewById(R.id.chimp_button);
  chimpButton.setOnClickListener(this);
  ImageView chimpImage = (ImageView) findViewById(R.id.chimp_imageview);
  chimpImage.setBackgroundResource(R.drawable.chimp_anim);
  chimpAnimation = (AnimationDrawable) chimpImage.getBackground();

  final ImageButton bubblesButton = (ImageButton) findViewById(R.id.bubbles_button);
  bubblesButton.setOnClickListener(this);
  ImageView bubblesImage = (ImageView) findViewById(R.id.bubbles_imageview);
  bubblesImage.setBackgroundResource(R.drawable.bubbles_anim);
  bubblesAnimation = (AnimationDrawable) bubblesImage.getBackground();  
 }

 public void onClick(View v) {
  if (mp != null) {
   mp.release();
  }

  Random generator = new Random();
  int randomIndex;

  switch(v.getId()){
  case R.id.chimp_button: 
    randomIndex = (generator.nextInt( 2 ) + 1);
    if (randomIndex == 1){
    mp = MediaPlayer.create(this, R.raw.chimp_1);
    }
    if (randomIndex == 2){
    mp = MediaPlayer.create(this, R.raw.chimp_2);
   }
   mp.start();

   chimpAnimation.setVisible(true,true);
   chimpAnimation.start();

   break;

  case R.id.bubbles_button: 
    randomIndex = (generator.nextInt( 3 ) + 1);
    if (randomIndex == 1){
    mp = MediaPlayer.create(this, R.raw.bubbles_1);
    }
    if (randomIndex == 2){
     mp = MediaPlayer.create(this, R.raw.bubbles_2);
   }
   if (randomIndex == 3){
     mp = MediaPlayer.create(this, R.raw.bubbles_3);
   }
   mp.start();

   bubblesAnimation.setVisible(true,true);
   bubblesAnimation.start();
   break;
  }
 }
}

А вот моя попытка воспроизведения кадров один за другим в ImageView, но он воспроизводит только первый и последний кадры:

    public void playAnimation(String name){
  final ImageView bubblesImageView = (ImageView) findViewById(R.id.bubbles_imageview);
  bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0003);

  mHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0015);
   }
  }, 500);

  mHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0025);
   }
  }, 500);

  mHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0035);
   }
  }, 500);


 }

Любая помощь будет оценена - спасибо

Ответы [ 3 ]

1 голос
/ 22 мая 2012

все ваши mHandler.postDelayed(new Runnable(){...}); срабатывают одновременно, например, через 500 мс необходимо, чтобы они запускались один за другим с помощью

nHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0015);
   }
  }, 500);

  mHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0025);
   }
  }, 1000);

  mHandler.postDelayed(new Runnable() {
   public void run() {
    bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0035);
   }
  }, 1500);

или наличие каждой работающей очереди в следующей очереди с задержкой в ​​500 мс, например,

mHandler.postDelayed(new Runnable() {
public void run() {
   bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0015);

   mHandler.postDelayed(new Runnable() {
   public void run() {
      bubblesImageView.setImageResource(R.drawable.bubbles_anim_v5_0025);
      }
   }, 1000); 
   }
}, 500);

Или вы можете создать массив ìnt со значением R.drawable.xxx, и каждые 500 мс просто отображать следующее изображение.

1 голос
/ 12 декабря 2014

Это чрезвычайно сложно, но выполнимо.Ключ заключается в том, чтобы перерабатывать ваши растровые изображения сразу после их использования.Посмотрите на этот класс-обертку, который кто-то написал, который будет обрабатывать все это для вас: http://snippetrepo.com/snippets/android-animation-without-outofmemoryerror

0 голосов
/ 28 декабря 2010

В моей компании возникла та же проблема, мы пытались создать заставку таким образом (и это было полным провалом). Если вы так сильно хотите получить какую-то анимацию, сгенерируйте видео из кадров PNG (я думаю, что FFMPEG может это сделать), а затем воспроизведите видео.

...