在Android中使用animationDrawable播放大型PNG帧动画

4
我有一个应用程序,其中的按钮在按下时会播放各种逐帧动画。这些动画是以.png文件序列的形式存储的。一些动画填充了一个小区域,使用animationDrawable时它们似乎可以正常播放。但是,一些动画填充了屏幕的大部分区域(即使它们大多数都是透明的),当我在手机上加载应用程序时(但不是模拟器),就会出现内存不足错误。我不能将它们作为视频文件播放,因为它们需要覆盖主屏幕。
我的主要问题是 - 是否有办法使用animationDrawable播放大型png序列动画(例如320x480的60帧)?
到目前为止,在我的研究中似乎没有任何方法可以避开内存限制...因此,我一直在寻找自己的方法,创建一个ImageView并用位图填充它,然后在延迟后依次替换每个帧。但是,使用这种技术,我的动画似乎只播放第一帧和最后一帧。
这是我尝试使用animationDrawable的代码 - "chimp"可以正常播放,但是当我添加“bubbles”(更大的图像)时,应用程序根本无法加载 - logCat显示:“ERROR/dalvikvm-heap(3248): 1008000-byte external allocation too large for this process... ERROR/AndroidRuntime(3248): java.lang.OutOfMemoryError: bitmap size exceeds VM budget”。
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

你的 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);

或者你可以构建一个 int 数组,其中包含 R.drawable.xxx 的值,并且每 500 毫秒显示下一张图片。


1

0
在我的公司,我们遇到了同样的问题。我们曾尝试以这种方式制作启动画面(但结果是彻底失败的)。如果你非常想要某种类型的动画效果,可以从PNG帧生成视频(我认为FFMPEG可以实现),然后播放该视频。

谢谢 - 我快要放弃尝试使用animationDrawable了... 您有关于编写自己的代码以顺序播放一系列位图的建议吗?(我上面测试了这个)。这种技术会太慢吗? - JoeD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接