I used to teach myself by frame animation, but I often have insomnia these days, and I can’t learn anything at night. So I should write a small Demo on Canvas. I am the only one who is so boring.

The renderings are as follows:

Before the code, introduce the mobile phone coordinate system, as shown in the figure below

Then draw a sketch, as follows:

The idea is to rotate the color background in a time-consuming thread to achieve the effect of running around.

Core:

1. Calculate the width and height of the View and the width and height of the rectangle, and then calculate the coordinate points of the rectangle.

 int canvasWidth = canvas.getWidth();       // Canvas width
        int canvasHeight = canvas.getHeight();     // Canvas height
        int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2.2)+Math.pow(canvasHeight/2.2)) +1; // Half the width and height of the square
Copy the code

2. Drawing background, running lamp, curtain

  // Start drawing the underlying background
        p.setColor(Color.WHITE);
        RectF oval2 = new RectF(0.0, canvasWidth, canvasHeight);// Set a new rectangle and scan the measurement
        canvas.drawRect(oval2,p);
        // Start drawing the running lights
        Paint p1=new Paint(p);
        Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax,
                new int[] { Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT); 
        p1.setShader(mShader);
        RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// Set a new rectangle
        canvas.drawRect(oval,p1);
        // Draw the curtain
        Paint p2=new Paint();
        p2.setColor(Color.BLACK);
        RectF oval3 = new RectF(30.30, canvasWidth- 30, canvasHeight- 30);// Set a new rectangle and scan the measurement
        canvas.drawRect(oval3,p2);
Copy the code

3. Find the pivot and start a time-consuming task.

   private Calendar mCalendar; // Time object
    public static final int START_CLOCK = 1000;// Enable the clock identifier
    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case DrawView.START_CLOCK:
                    mCalendar = mCalendar.getInstance();
                    invalidate();
                    sendEmptyMessageDelayed(DrawView.START_CLOCK, 10);
                    break;
                case DrawView.STOP_CLOCK:
                    break;
                default:
                    break; }}};Copy the code

4. Set the color square rotation

 canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2);
Copy the code

5. Reverse rotate the curtain according to the color square (if not set, rotate with the square);

  canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2);
Copy the code

The source code is as follows:

1. Complete Java file

public class MarqueeView extends View {
    private Calendar mCalendar; // Time object
    public static final int START_CLOCK = 1000;// Enable the clock identifier
    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case DrawView.START_CLOCK:
                    mCalendar = mCalendar.getInstance();
                    invalidate();
                    sendEmptyMessageDelayed(DrawView.START_CLOCK, 10);
                    break;
                case DrawView.STOP_CLOCK:
                    break;
                default:
                    break; }}};public MarqueeView(Context context) {
        super(context);
    }

    public MarqueeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mCalendar = mCalendar.getInstance();
        if (mCalendar == null) {
            mCalendar = mCalendar.getInstance();
        }
        mHandler.sendEmptyMessage(START_CLOCK);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawAxis(canvas);
    }

    / / to draw
    private void drawAxis(Canvas canvas){
        Paint p=new Paint();
        int canvasWidth = canvas.getWidth();       // Canvas width
        int canvasHeight = canvas.getHeight();     // Canvas height
        int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2.2)+Math.pow(canvasHeight/2.2)) +1; // Half the width and height of the square
        int sec = mCalendar.get(Calendar.SECOND);// Get the current number of seconds
        // Start drawing the underlying background
        p.setColor(Color.WHITE);
        RectF oval2 = new RectF(0.0, canvasWidth, canvasHeight);// Set a new rectangle and scan the measurement
        canvas.drawRect(oval2,p);
        canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2);
        // Start drawing the running lights
        Paint p1=new Paint(p);
        Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax,
                new int[] { Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
        p1.setShader(mShader);
        RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// Set a new rectangle and scan the measurement
        canvas.drawRect(oval,p1);
        // Draw the curtain
        Paint p2=new Paint();
        canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2);
        p2.setColor(Color.BLACK);
        RectF oval3 = new RectF(30.30, canvasWidth- 30, canvasHeight- 30);// Set a new rectangle and scan the measurementcanvas.drawRect(oval3,p2); }}Copy the code

2. Call in XML

<com................ MarqueeView android:layout_width="match_parent"
    android:layout_height="match_parent"/>
Copy the code

Pay attention to

Make animation part of the trouble, you can use the property animation to calculate their own color can also make gradients, set infinite loop.

Ex. :

animator = ValueAnimator.ofInt(0, screenSize.x-50); // Property animation interpolator 'animator.setInterpolator(new LinearInterpolator()); ` animator.setDuration(2000); // animator.setrepeatCount (-1); ` animator.setRepeatMode(ValueAnimator.RESTART); ` animator. AddUpdateListener ((animation - > {/ / lambda expressions ` animatedValue = (int) animation. GetAnimatedValue (); ` postInvalidateDelayed(1000/60); // Redraw and refresh the entire View 60 frames. '})); ` animator.start(); // Start the animation 'Copy the code