How to animate full-screen stripes moving from left to right

I would like to create an animation, but I do not know how to start with it. Here is the image.

I want red and stripes to animate from left to right. (Translate) Animations are not new to me. Moving an object on the screen is easy because we have a background behind it. In my case, this is a background that should move.

If I use an image, then it will not be possible to fill in the empty space that the image leaves after moving to the right. One idea is to programmatically fill the screen initially with stripes, start moving them from left to right, and when one starts leaving the screen, and then draw a new line on the left, but considering that the stripes are not 1px wide, I don’t know how to do it .

Another way would be to use an image wider by 2 stripes than on the screen. On the left are two invisible stripes. When the image is moved to the right (end of animation), we will restart the animation. I wonder if this will lead to any interruption or whether it will look as smooth for the user.

Any ideas? Should I use andengine or something similar for this?

+4
source share
2 answers

You can use a custom drawable that simply draws rectangles on the canvas. Below is a basic example, just use it as

BackgroundDrawable bg = new BackgroundDrawable();
anyView.setBackground(bg);
bg.start();

Here is a basic working implementation:

public class BackgroundDrawable extends Drawable implements Runnable, Animatable {
    private static final long FRAME_DELAY = 1000 / 60;
    private boolean mRunning = false;
    private long mStartTime;
    private int mDuration = 1000;

    private Paint mPaint;
    private int mStripes = 7;


    private void init() {
        if (mPaint == null) {
            mPaint = new Paint();
            mPaint.setColor(Color.WHITE);
            mPaint.setAntiAlias(true);
            mPaint.setStyle(Paint.Style.FILL);
        }
    }

    @Override
    public void draw(Canvas canvas) {
        Rect bounds = getBounds();
        if (isRunning()) {
            // animation in progress
            final int save = canvas.save();

            long timeDiff = SystemClock.uptimeMillis() - mStartTime;
            canvas.clipRect(bounds);

            float progress = ((float) timeDiff) / ((float) mDuration); // 0..1

            float width = bounds.width() / (mStripes * 2);

            for (int i = 0; i < mStripes * 2 + 2; i++) {
                mPaint.setColor(i % 2 == 0 ? Color.RED : Color.WHITE);
                canvas.drawRect(bounds.left + width * (i - 1) + progress * 2 * width, bounds.top, bounds.left + width * i + progress * 2* width, bounds.bottom, mPaint);
            }

            canvas.restoreToCount(save);
        } else {
            // todo draw normal
        }
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        init();
    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return 0;
    }

    @Override
    public void start() {
        if (mRunning) stop();
        mRunning = true;
        mStartTime = SystemClock.uptimeMillis();
        invalidateSelf();
        scheduleSelf(this, SystemClock.uptimeMillis() + FRAME_DELAY);
    }

    @Override
    public void stop() {
        unscheduleSelf(this);
        mRunning = false;
    }

    @Override
    public boolean isRunning() {
        return mRunning;
    }

    @Override
    public void run() {
        invalidateSelf();
        long uptimeMillis = SystemClock.uptimeMillis();
        if (uptimeMillis + FRAME_DELAY < mStartTime + mDuration) {
            scheduleSelf(this, uptimeMillis + FRAME_DELAY);
        } else {
            mRunning = false;
            start();
        }
    }
}

, : .

+2

, onDraw()

0

Source: https://habr.com/ru/post/1623156/


All Articles