【问题标题】:Playing large PNG frame animation in android with animationDrawable使用animationDrawable在android中播放大型PNG帧动画
【发布时间】:2010-12-28 07:07:10
【问题描述】:

我有一个带有按钮的应用程序,当按下这些按钮时,这些按钮会播放各种逐帧动画。动画存储为 .png 文件序列。一些动画填充了一个小区域,并且使用 animationDrawable 似乎可以正常播放。但是,一些动画填满了屏幕的很大一部分(即使它们使用 Alpha 通道大多是透明的),并且当应用程序加载到我的手机(但不是模拟器)上时出现内存不足错误。我无法将它们作为视频文件播放,因为它们需要覆盖主屏幕。

我的主要问题 - 有没有办法使用 animationDrawable 播放大型 png 序列动画(比如 320x480 的 60 帧)?

到目前为止,在我的研究中似乎没有任何方法可以解决内存限制...所以我一直在研究创建自己的方法来创建 ImageView 并用位图填充它,然后依次替换延迟后每帧的位图。但是,使用这种技术,我的动画似乎只播放第一帧和最后一帧。

这是我尝试使用 animationDrawable 的代码 - “黑猩猩”播放正常,但是当我添加“气泡”(较大的图像)时,应用程序根本无法加载 - logCat 显示:“错误/ dalvikvm-heap(3248): 1008000 字节的外部分配对于这个进程来说太大了... 错误/AndroidRuntime(3248): java.lang.OutOfMemoryError: 位图大小超过了 VM 预算 "

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


 }

任何帮助将不胜感激 - 谢谢

【问题讨论】:

    标签: android animation png imageview


    【解决方案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);
    

    或者您可以使用 R.drawable.xxx 值构造一个 ìnt 数组,并且每 500 毫秒显示下一张图像。

    【讨论】:

      【解决方案2】:

      这是一件极其困难的事情,但它是可行的。关键是在使用后立即回收位图。查看某人编写的这个包装类,它将为您处理所有这些: http://snippetrepo.com/snippets/android-animation-without-outofmemoryerror

      【讨论】:

        【解决方案3】:

        在我的公司中,我们也遇到了同样的问题,我们试图以这种方式制作启动画面(这完全是一场灾难)。如果你非常想得到某种动画,从 PNG 帧生成视频(我认为 FFMPEG 可以做到),然后播放视频。

        【讨论】:

        • 谢谢-我即将放弃尝试使用animationDrawable...您对编写我自己的代码来顺序播放一系列位图有什么建议吗? (我对此的测试在上面)。这种技术会不会太慢?
        猜你喜欢
        • 2012-01-16
        • 1970-01-01
        • 2011-02-21
        • 2011-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-25
        • 1970-01-01
        相关资源
        最近更新 更多