android - Sprite 图像动画

标签 android imageview android-animation android-imageview android-custom-view

我试图找到简单的方法来在我的 Android 项目上为 Sprite 图像设置动画。发现一些复杂的解决方案,并且在 RecyclerViewAdapter 上使用它们并不那么容易。为什么它不能通过自定义 View 变得简单。

这是一个要显示为动画的示例 Sprite 图像。 https://cdn.codeandweb.com/blog/2016/05/10/how-to-create-a-sprite-sheet/spritestrip.png

最佳答案

这个自定义 View 非常适合 Sprite 表情符号图像。

如果有人在Android上需要 Sprite 图像动画可以使用这个自定义ImageView。

public class AnimatedImageView extends AppCompatImageView {

    private static final String KEY_ACTIVITY = "activity";
    private static final String KEY_FRAME_COUNT = "frameCount";
    private static final String KEY_FRAME_SPEED = "frameSpeed";
    private static final String KEY_LOOP_ENABLE = "loopEnable";
    private static final String KEY_SOURCE_URL = "sourceUrl";

    private AppCompatActivity activity;

    private Bitmap sourceBitmap;
    private Bitmap croppedBitmap;

    private int xPos;

    private int frameCount;
    private int frameSpeed;
    private int frameWidth, frameHeight;

    private int sourceWidth;

    private boolean loopEnable;

    private Timer timer;

    public AnimatedImageView(Context context) {
        super(context);
    }

    public AnimatedImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public AnimatedImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void start(Map <String,Object> map) {
        this.activity = (AppCompatActivity) map.get(KEY_ACTIVITY);
        this.frameCount = (int) map.get(KEY_FRAME_COUNT);
        this.frameSpeed = (int) map.get(KEY_FRAME_SPEED);
        this.loopEnable = (boolean) map.get(KEY_LOOP_ENABLE);
        new DownloadImage().execute(String.valueOf(map.get(KEY_SOURCE_URL)));
    }

    private void animateBitmap() {
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                prepareBitmap();
            }
        }, 0, frameSpeed);
    }

    private void prepareBitmap() {
        croppedBitmap = Bitmap.createBitmap(sourceBitmap, xPos, 0, frameWidth, frameHeight);
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                setImageBitmap(croppedBitmap);

                if (xPos + frameWidth >= sourceWidth) {
                    if (loopEnable) {
                        xPos = 0;
                    } else {
                        xPos = 0;
                        timer.cancel();
                        return;
                    }
                }

                xPos = xPos + frameWidth;
            }
        });
    }

    private void buildView(Bitmap bitmap) {
        sourceBitmap = bitmap;
        frameWidth = sourceBitmap.getWidth() / frameCount;
        frameHeight = sourceBitmap.getHeight();
        sourceWidth = sourceBitmap.getWidth();

        measure(frameWidth, frameHeight);

        animateBitmap();
    }

    public int getFrameCount() {
        return frameCount;
    }

    public void setFrameCount(int frameCount) {
        this.frameCount = frameCount;
    }

    public int getFrameSpeed() {
        return frameSpeed;
    }

    public void setFrameSpeed(int frameSpeed) {
        this.frameSpeed = frameSpeed;
    }

    public boolean isLoopEnable() {
        return loopEnable;
    }

    public void setLoopEnable(boolean loopEnable) {
        this.loopEnable = loopEnable;
    }

    private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
        @Override
        protected Bitmap doInBackground(String... url) {
            String imageURL = url[0];
            Bitmap bitmap = null;

            try {
                InputStream input = new URL(imageURL).openStream();
                bitmap = BitmapFactory.decodeStream(input);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            buildView(bitmap);
        }
    }

    public static class AnimationBuilder {

        private final int DEFAULT_FRAME_COUNT = 20;
        private final int DEFAULT_FRAME_SPEED = 40;

        private AppCompatActivity activity;
        private int frameCount = DEFAULT_FRAME_COUNT;
        private int frameSpeed = DEFAULT_FRAME_SPEED;
        private boolean loopEnable;
        private String sourceUrl = "";

        private AppCompatActivity getAppCompatActivity() {
            return activity;
        }

        public AnimationBuilder from(AppCompatActivity activity) {
            this.activity = activity;
            return this;
        }

        private int getFrameCount() {
            return frameCount;
        }

        public AnimationBuilder frameCount(int frameCount) {
            this.frameCount = frameCount;
            return this;
        }

        private int getFrameSpeed() {
            return frameSpeed;
        }

        public AnimationBuilder frameSpeed(int frameSpeed) {
            this.frameSpeed = frameSpeed;
            return this;
        }

        private boolean isLoopEnable() {
            return loopEnable;
        }

        public AnimationBuilder loopEnable(boolean loopEnable) {
            this.loopEnable = loopEnable;
            return this;
        }

        private String getSourceUrl() {
            return sourceUrl;
        }

        public AnimationBuilder load(String sourceUrl) {
            this.sourceUrl = sourceUrl;
            return this;
        }

        public Map<String, Object> build() {
            Map<String, Object> builtMap = new HashMap<>();
            builtMap.put(KEY_ACTIVITY, getAppCompatActivity());
            builtMap.put(KEY_FRAME_COUNT, getFrameCount());
            builtMap.put(KEY_FRAME_SPEED, getFrameSpeed());
            builtMap.put(KEY_LOOP_ENABLE, isLoopEnable());
            builtMap.put(KEY_SOURCE_URL, getSourceUrl());
            return builtMap;
        }
    }
}

用法:

要使用此自定义 ImageView,您需要知道帧计数。

仅适用于图像网址。

问题帧数为 6 的图像

yourAnimatedImageView.start(new AnimatedImageView.AnimationBuilder()
            .from(activity)
            .frameCount(6)
            .frameSpeed(50)
            .load("https://cdn.codeandweb.com/blog/2016/05/10/how-to-create-a-sprite-sheet/spritestrip.png")
            .loopEnable(false).build());

希望它能帮助那些正在寻找在 Android 上动画 Sprite 图像的解决方案的人。

关于android - Sprite 图像动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48244215/

相关文章:

Canvas 上的 Android 文本大小与 TextView 中的文本大小不同

android - 旋转 textview 及其背景 View

快速,旋转 ImageView 并将旋转 ImageView 设置为 uibutton

android - 我怎样才能把一个不在屏幕上的位图

android - 如何重复属性动画?

java - 在 Android 中返回特定位图而不是整个 View

android - 无法创建类 ViewModel kotlin 的实例

android - 使用 startOffset 的动画反转

java - Android上的JavaFX-Gradle找不到JDK

android - 单个 ScrollView 中多个图像的滞后