android - 显示逐帧动画android的最有效方法

标签 android android-animation

我正在尝试通过更改 ImageView 中的图像来逐帧显示动画。我尝试在 xml 中绘制动画,并在处理程序中更改 imageview 的位图。我还尝试在数组列表中仅存储三个位图(以避免内存不足)作为缓存机制,但改进很少。我需要迭代 36 张图像以获得完整的动画。我面临的问题是,在我使用的所有方法中,我都无法在给定的 50 毫秒时间内完成动画。图像的范围从最小的 250 kb 到最大的 540 kb。动画的 fps 真的很低。由于应用程序的 ios 版本已准备就绪,因此我不得不显示与 ios 版本一致的动画。我是 renderscript 和 opengl 的菜鸟。有什么方法可以在 50-60 毫秒内为大图像显示流畅的动画。非常感谢任何提示或建议。这是动画的快照: 这是 link对于任何感兴趣的人,我的图片。 enter image description here

最佳答案

我写了一个简单的 Activity 来做最基本的事情:

在线程中加载所有位图,然后每 40 毫秒将更改发布到 ImageView。

package mk.testanimation;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import java.util.ArrayList;

public class MainActivity extends Activity {
    ImageView mImageView;

    private int mImageRes[] = new int[]{
        R.drawable.s0,
        R.drawable.s1,
        R.drawable.s2,
        R.drawable.s3,
        R.drawable.s4,
        R.drawable.s5,
        R.drawable.s6,
        R.drawable.s7,
        R.drawable.s8,
        R.drawable.s9,
        R.drawable.s10,
        R.drawable.s11,
        R.drawable.s12,
        R.drawable.s13,
        R.drawable.s14,
        R.drawable.s15,
        R.drawable.s16,
        R.drawable.s17,
        R.drawable.s18,
        R.drawable.s19,
        R.drawable.s20,
        R.drawable.s21,
        R.drawable.s22,
        R.drawable.s23,
        R.drawable.s24,
        R.drawable.s25,
        R.drawable.s26,
        R.drawable.s27,
        R.drawable.s28,
        R.drawable.s29,
        R.drawable.s30,
        R.drawable.s31,
        R.drawable.s32,
        R.drawable.s33,
        R.drawable.s34,
        R.drawable.s35,
    };

    private ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(mImageRes.length);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Handler handler = new Handler();
        mImageView = new ImageView(this);
        setContentView(mImageView);
        Thread important = new Thread() {
            @Override
            public void run() {
                long timestamp = System.currentTimeMillis();
                for (int i = 0; i < mImageRes.length; i++) {
                    mBitmaps.add(BitmapFactory.decodeResource(getResources(), mImageRes[i]));
                }
                Log.d("ANIM-TAG", "Loading all bitmaps took " + (System.currentTimeMillis() - timestamp) + "ms");
                for (int i = 0; i < mBitmaps.size(); i++) {
                    final int idx = i;
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mImageView.setImageBitmap(mBitmaps.get(idx));
                        }
                    }, i * 40);
                }
            }
        };
        important.setPriority(Thread.MAX_PRIORITY);
        important.start();
    }
}

这在我的 Nexus 7 上看起来相当不错,但加载所有位图确实需要 4 秒多一点。

可以提前加载位图吗?

另外,它不会节省很多,但你的 png 在透明空间周围有一堆填充。您可以裁剪它们并稍微减少内存。否则压缩图像也会有所帮助(例如限制使用的颜色数量)。

理想情况下,在上述解决方案中,您会在位图不再使用后立即回收它们。

此外,如果内存太重,您可以按照您提到的那样做,并有一个位图缓冲区,但我很确定它需要超过 3 张图像。

祝你好运。

编辑:尝试 2。 首先,我将所有图像裁剪为 590x590。这减少了大约 1mb 的图像。然后我创建了一个新类,它有点“忙”并且没有固定的帧速率,但会在图像准备好后立即渲染:

package mk.testanimation;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;

import java.util.ArrayList;

public class MainActivity extends Activity {
    ImageView mImageView;

    private int mImageRes[] = new int[]{R.drawable.s0, R.drawable.s1, R.drawable.s2, R.drawable.s3, R.drawable.s4, R.drawable.s5, R.drawable.s6, R.drawable.s7, R.drawable.s8, R.drawable.s9, R.drawable.s10, R.drawable.s11, R.drawable.s12, R.drawable.s13, R.drawable.s14, R.drawable.s15, R.drawable.s16, R.drawable.s17, R.drawable.s18, R.drawable.s19, R.drawable.s20, R.drawable.s21, R.drawable.s22, R.drawable.s23, R.drawable.s24, R.drawable.s25, R.drawable.s26, R.drawable.s27, R.drawable.s28, R.drawable.s29, R.drawable.s30, R.drawable.s31, R.drawable.s32, R.drawable.s33, R.drawable.s34, R.drawable.s35};

    private ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(mImageRes.length);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final long timestamp = System.currentTimeMillis();
        final Handler handler = new Handler();
        mImageView = new ImageView(this);
        setContentView(mImageView);
        Thread important = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < mImageRes.length; i++) {
                    mBitmaps.add(BitmapFactory.decodeResource(getResources(), mImageRes[i]));
                }
            }
        };
        important.setPriority(Thread.MAX_PRIORITY);
        important.start();
        Thread drawing = new Thread() {
            @Override
            public void run() {
                int i = 0;
                while (i < mImageRes.length) {
                    if (i >= mBitmaps.size()) {
                        Thread.yield();
                    } else {
                        final Bitmap bitmap = mBitmaps.get(i);
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                mImageView.setImageBitmap(bitmap);
                            }
                        });
                        i++;
                    }
                }
                Log.d("ANIM-TAG", "Time to render all frames:" + (System.currentTimeMillis() - timestamp) + "ms");
            }
        };
        drawing.setPriority(Thread.MAX_PRIORITY);
        drawing.start();
    }
}

上面的代码几乎立即开始渲染,在我的 2012 Nexus 7 上用了不到 4 秒。

作为最后的努力,我将所有图像转换为 8 位 PNG 而不是 32 位。这使渲染不到 2 秒!

我敢打赌,您最终得到的任何解决方案都会因使图像尽可能小而受益。

再次——祝你好运!

关于android - 显示逐帧动画android的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24242268/

相关文章:

php - utf8_encode 不编码特殊字符 ě/š/č/ř/ž/ý/á 等

java - Android:如何禁用选项卡选择时的默认弹出 TabLayout 动画

java - android View 翻转动画?

android - 如何在整个翻译动画中实现均匀速度?

android - AlphaAnimation 对象不会更改动画 View 的 alpha 属性,为什么?

java - 当使用回收器 View 和 View 模型获取数据时,映射器函数返回空值

android - 如何使用Gradle绕过登录屏幕

android - 如何以编程方式在 Android 中使用 OpenGL ES 2.0 动态绘制虚线?

android - 带动画的窗口管理器

Android onKey() 永远不会被调用