【问题标题】:Create animated splash screen using frames on Android在 Android 上使用框架创建动画启动画面
【发布时间】:2012-12-29 16:58:25
【问题描述】:

所以这就是交易,我已经搜索了每个问题和在线链接,但没有一个有用。 我的初始屏幕有 120 帧 .jpg 格式的动画。我知道 jpeg 被转换为内存上的位图,所以这就是我得到 OutOfMemoryError 的原因。我制作动画的最大帧数是 10。有没有办法逐帧执行此操作,或者我应该尝试其他方法。这是我的代码:

    final AnimationDrawable anim = new AnimationDrawable();
    anim.setOneShot(true);

    for (int i = 1; i <= 120; i++) 
    {
        Drawable logo = getResources().getDrawable(getResources()
                  .getIdentifier("l"+i, "drawable", getPackageName()));

        anim.addFrame(logo, 50);
        if (i % 3 == 0)
        {
            System.gc();
        }
    }

    ImageView myImageView = (ImageView) findViewById(R.id.SplashImageView);
    myImageView.setBackgroundDrawable(anim);
    myImageView.post(new Runnable()
    {
       public void run()
       {
          anim.start();
       }
    });

我已将 120 个 jpeg 放在带有“l”前缀的可绘制文件夹下(例如 l1、l2 等)。 我每 3 个 jpeg 进行一次垃圾收集,但这无济于事。

【问题讨论】:

  • 你试过在 xml 中使用 Animation-List 吗?
  • 是的...复制粘贴 120 次“几乎”相同的东西真的很痛苦。 (我很愚蠢,之前没有尝试过几张jpeg)
  • 120 帧对于任何动画来说都太多了。

标签: android animation frame out-of-memory splash-screen


【解决方案1】:

您可以尝试在没有AnimationDrawable 的情况下使用Handler.postDelayed。像这样的:

final ImageView image = (ImageView) findViewById(R.id.SplashImageView);
final Handler handler = new Handler();

final Runnable animation = new Runnable() {
    private static final int MAX = 120;
    private static final int DELAY = 50;

    private int current = 0;

    @Override
    public void run() {
        final Resources resources = getResources();
        final int id = resources.getIdentifier("l" + current, "drawable", getPackageName());
        final Drawable drawable = resources.getDrawable(id);

        image.setBackgroundDrawable(drawable);
        handler.postDelayed(this, DELAY);
        current = (current + 1) % MAX;
    }
};

handler.post(animation);

此解决方案需要更少的内存,因为它一次只保留一个可绘制对象。

您可以使用handler.removeCallbacks(animation); 取消动画。

如果要制作一次性动画,可以有条件地调用handler.postDelayed

if (current != MAX - 1) {
    handler.postDelayed(this, DELAY);
}

【讨论】:

  • 这几乎正是我想要的!非常感谢。虽然它很滞后,而且帧分辨率真的很差。
  • 这段代码对帧分辨率没有任何作用,因此您应该使用质量更好的帧。或者尝试使用setImageDrawable 而不是setBackgroundDrawable
  • 另一个愚蠢的问题。我如何让它停止?它无限运行,结果我收到一个找不到资源的错误(l121 不存在)
  • hmmm...您不应该收到此错误...无论如何,请查看我的更新答案,它可能会对您有所帮助
【解决方案2】:

需要调用̶.̶r̶e̶c̶y̶c̶l̶e̶(̶)̶对位图你请勿使用̶a̶n̶y̶m̶o̶r̶e̶.̶否则他们不会被垃圾收集̶p̶r̶o̶p̶e̶r̶l̶y̶.̶ P>

同样在清单集中使用大堆为真。这给了你更多的呼吸空间。 >)

【讨论】:

  • 你能说得更具体点吗?一旦 AnimationDrawable “started()”,我如何调用回收?
  • 啊,我的错。抱歉,我需要一杯咖啡 :) 看起来不对。您使用的是可绘制对象而不是位图。无需对这些调用回收。对不起..
  • 嗯...你可能必须使用 openGL 作为你的启动屏幕,正如这篇文章所建议的那样:stackoverflow.com/questions/5136385/…
【解决方案3】:

我尝试了所有这些解决方案,每一个都变得更好 :D 我可以使用更多的帧和更高的分辨率,但仍然不能让经理满意 :( 我发现最好的解决方案是使用视频而不是帧,它甚至可以像一个魅力低内存设备我在 xperia u 上使用视频编解码器 (H.264 mp4) 测试了 150 帧,每个尺寸为 480*854,内存为 256mb

【讨论】:

    猜你喜欢
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 2018-12-09
    • 2021-12-26
    • 2014-02-13
    相关资源
    最近更新 更多