Android Drawing, Canvas Learning Notes

Keywords: Android Mobile github Programming

User interface is an important aspect in deciding whether Android applications will be accepted by users. In order to provide a friendly user interface, it is necessary to use pictures in applications. Android system provides rich image function support, including static image processing and animation.
Android system provides ImageView to display ordinary static pictures, Animation Drawable to develop frame-by-frame animation, and animation can be used for ordinary pictures.
In addition to using existing pictures, Android applications often need to dynamically generate pictures at runtime, such as a mobile game. The game interface looks rich and colorful, and can dynamically change with the user's actions. This requires drawing support from Android.

Canvas

Readers with Swing programming experience know that the idea of drawing in Swing is to develop a custom class that inherits JPanel and rewrites JPanel's paint (Graphics) method. Similar to Android's drawing, Android's drawing should inherit the View component and rewrite its onDraw (Canvas canvas) method.
Rewriting onDraw (Canvas canvas) involves a drawing API: Canvas. Canvas represents the canvas of "attachment" and designated View. The user interface is an important aspect in deciding whether Android applications are accepted by users. In order to provide a friendly user interface, it is necessary to use pictures in applications. Android system provides rich image function support, including static image processing and animation.
Android system provides ImageView to display ordinary static pictures, Animation Drawable to develop frame-by-frame animation, and animation can be used for ordinary pictures.
In addition to using existing pictures, Android applications often need to dynamically generate pictures at runtime, such as a mobile game. The game interface looks rich and colorful, and can dynamically change with the user's actions. This requires drawing support from Android.
Canvas provides the following table methods for drawing various graphics

Canvas also provides the following methods for coordinate transformation.
rotate(float degrees, float px, float py): perform rotation transformation on Canvas
scale(float sx,float sy,float px, float py): Scale the Canvas
skew(float sx,float sy): perform tilt transform on Canvas
translate(float dx, float dy): Mobile Canvas. Move the DX distance to the right (dx is negative, that is, to the left); move the dy distance downward (dy is negative, that is, move up)
The method provided by Canvas also involves an API: Paint, Paint represents the brush on Canvas, so Paint class is mainly used to set the drawing style, including brush color, brush stroke thickness, filling style and so on.
The following table is the method provided by Paint:

In the drawing method provided by Canvas, an API: Path is also used. Path represents any graph linked by any number of lines. When Canvas draws according to Path, it can draw any shape.
The following program demonstrates how to draw basic set graphics in Android applications. The key to this program is a custom View component, which rewrites the onDraw (Canvase) method of modifying the View component, and then draws a large number of geometric figures on the Canvas. The code for customizing View is as follows
Complete project code can be downloaded to my GitHub address https://github.com/Willraylei/CanvasTest

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View
{
    public MyView(Context context, AttributeSet set)
    {
        super(context, set);
    }
    @Override
    // Rewrite the method and draw
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        // Draw the whole canvas white
        canvas.drawColor(Color.WHITE);
        Paint paint = new Paint();
        // Sawtooth removal
        paint.setAntiAlias(true);
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);
        int viewWidth = this.getWidth();
        // Draw a circle
        canvas.drawCircle(viewWidth / 10 + 10, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // Draw a square
        canvas.drawRect(10 , viewWidth / 5 + 20 , viewWidth / 5 + 10
            , viewWidth * 2 / 5 + 20 , paint);
        // draw rectangle
        canvas.drawRect(10, viewWidth * 2 / 5 + 30, viewWidth / 5 + 10
            , viewWidth / 2 + 30, paint);
        RectF re1 = new RectF(10, viewWidth / 2 + 40
            , 10 + viewWidth / 5 ,viewWidth * 3 / 5 + 40);
        // Draw rounded rectangle
        canvas.drawRoundRect(re1, 15, 15, paint);
        RectF re11 = new RectF(10, viewWidth * 3 / 5 + 50
            , 10 + viewWidth / 5 ,viewWidth * 7 / 10 + 50);
        // Draw an ellipse
        canvas.drawOval(re11, paint);
        // Define a Path object, enclosed in a triangle
        Path path1 = new Path();
        path1.moveTo(10, viewWidth * 9 / 10 + 60);
        path1.lineTo(viewWidth / 5 + 10, viewWidth * 9 / 10 + 60);
        path1.lineTo(viewWidth / 10 + 10, viewWidth * 7 / 10 + 60);
        path1.close();
        // Draw triangles according to Path
        canvas.drawPath(path1, paint);
        // Define a Path object, enclosed in a Pentagon
        Path path2 = new Path();
        path2.moveTo(10 + viewWidth / 15, viewWidth * 9 / 10 + 70);
        path2.lineTo(10 + viewWidth * 2 / 15, viewWidth * 9 / 10 + 70);
        path2.lineTo(10 + viewWidth / 5, viewWidth + 70);
        path2.lineTo(10 + viewWidth / 10, viewWidth * 11/10 + 70);
        path2.lineTo(10 , viewWidth + 70);
        path2.close();
        // Draw a Pentagon according to Path
        canvas.drawPath(path2, paint);
        // Drawing after setting filling style - -------------------------------------------------------------------------------------------------------------------
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);
        // Draw a circle
        canvas.drawCircle(viewWidth * 3 / 10 + 20, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // Draw a square
        canvas.drawRect(viewWidth / 5 + 20 , viewWidth / 5 + 20
            , viewWidth * 2 / 5 + 20 , viewWidth * 2 / 5 + 20 , paint);
        // draw rectangle
        canvas.drawRect(viewWidth / 5 + 20, viewWidth * 2 / 5 + 30
            , viewWidth * 2 / 5 + 20 , viewWidth / 2 + 30, paint);
        RectF re2 = new RectF(viewWidth / 5 + 20, viewWidth / 2 + 40
            , 20 + viewWidth * 2 / 5 ,viewWidth * 3 / 5 + 40);
        // Draw rounded rectangle
        canvas.drawRoundRect(re2, 15, 15, paint);
        RectF re21 = new RectF(20 + viewWidth / 5, viewWidth * 3 / 5 + 50
            , 20 + viewWidth * 2 / 5 ,viewWidth * 7 / 10 + 50);
        // Draw an ellipse
        canvas.drawOval(re21, paint);
        // Define a Path object, enclosed in a triangle
        Path path3 = new Path();
        path3.moveTo(20 + viewWidth / 5, viewWidth * 9 / 10 + 60);
        path3.lineTo(viewWidth * 2 / 5 + 20, viewWidth * 9 / 10 + 60);
        path3.lineTo(viewWidth * 3 / 10 + 20, viewWidth * 7 / 10 + 60);
        path3.close();
        // Draw triangles according to Path
        canvas.drawPath(path3, paint);
        // Define a Path object, enclosed in a Pentagon
        Path path4 = new Path();
        path4.moveTo(20 + viewWidth *4 / 15, viewWidth * 9 / 10 + 70);
        path4.lineTo(20 + viewWidth / 3, viewWidth * 9 / 10 + 70);
        path4.lineTo(20 + viewWidth * 2 / 5, viewWidth + 70);
        path4.lineTo(20 + viewWidth * 3 / 10, viewWidth * 11/10 + 70);
        path4.lineTo(20 + viewWidth / 5 , viewWidth + 70);
        path4.close();
        // Draw a Pentagon according to Path
        canvas.drawPath(path4, paint);
        // Drawing after setting the gradient - -------------------------------------------------------------------------------------------------------------------
        // Setting Gradient for Paint
        Shader mShader = new LinearGradient(0, 0, 40, 60
            , new int[] {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW }
            , null , Shader.TileMode.REPEAT);
        paint.setShader(mShader);
        //Setting Shadows
        paint.setShadowLayer(25 , 20 , 20 , Color.GRAY);
        // Draw a circle
        canvas.drawCircle(viewWidth / 2 + 30, viewWidth / 10 + 10
            , viewWidth / 10, paint);
        // Draw a square
        canvas.drawRect(viewWidth * 2 / 5 + 30 , viewWidth / 5 + 20
            , viewWidth * 3 / 5 + 30 , viewWidth * 2 / 5 + 20 , paint);
        // draw rectangle
        canvas.drawRect(viewWidth * 2 / 5 + 30, viewWidth * 2 / 5 + 30
            , viewWidth * 3 / 5 + 30 , viewWidth / 2 + 30, paint);
        RectF re3 = new RectF(viewWidth * 2 / 5 + 30, viewWidth / 2 + 40
            , 30 + viewWidth * 3 / 5 ,viewWidth * 3 / 5 + 40);
        // Draw rounded rectangle
        canvas.drawRoundRect(re3, 15, 15, paint);
        RectF re31 = new RectF(30 + viewWidth *2 / 5, viewWidth * 3 / 5 + 50
            , 30 + viewWidth * 3 / 5 ,viewWidth * 7 / 10 + 50);
        // Draw an ellipse
        canvas.drawOval(re31, paint);
        // Define a Path object, enclosed in a triangle
        Path path5 = new Path();
        path5.moveTo(30 + viewWidth * 2/ 5, viewWidth * 9 / 10 + 60);
        path5.lineTo(viewWidth * 3 / 5 + 30, viewWidth * 9 / 10 + 60);
        path5.lineTo(viewWidth / 2 + 30, viewWidth * 7 / 10 + 60);
        path5.close();
        // Draw triangles according to Path
        canvas.drawPath(path5, paint);
        // Define a Path object, enclosed in a Pentagon
        Path path6 = new Path();
        path6.moveTo(30 + viewWidth * 7 / 15, viewWidth * 9 / 10 + 70);
        path6.lineTo(30 + viewWidth * 8 / 15, viewWidth * 9 / 10 + 70);
        path6.lineTo(30 + viewWidth * 3 / 5, viewWidth + 70);
        path6.lineTo(30 + viewWidth / 2, viewWidth * 11/10 + 70);
        path6.lineTo(30 + viewWidth * 2 / 5 , viewWidth + 70);
        path6.close();
        // Draw a Pentagon according to Path
        canvas.drawPath(path6, paint);
        // Drawing after setting character size - ---------------------------------------------------------------------------------------------------------------------
        paint.setTextSize(48);
        paint.setShader(null);
        // Draw7Strings
        canvas.drawText(getResources().getString(R.string.circle)
            , 60 + viewWidth * 3 / 5, viewWidth / 10 + 10, paint);
        canvas.drawText(getResources().getString(R.string.square)
            , 60 + viewWidth * 3 / 5, viewWidth * 3 / 10 + 20, paint);
        canvas.drawText(getResources().getString(R.string.rect)
            , 60 + viewWidth * 3 / 5, viewWidth * 1 / 2 + 20, paint);
        canvas.drawText(getResources().getString(R.string.round_rect)
            , 60 + viewWidth * 3 / 5, viewWidth * 3 / 5 + 30, paint);
        canvas.drawText(getResources().getString(R.string.oval)
            , 60 + viewWidth * 3 / 5, viewWidth * 7 / 10 + 30, paint);
        canvas.drawText(getResources().getString(R.string.triangle)
            , 60 + viewWidth * 3 / 5, viewWidth * 9 / 10 + 30, paint);
        canvas.drawText(getResources().getString(R.string.pentagon)
            , 60 + viewWidth * 3 / 5, viewWidth * 11 / 10 + 30, paint);
    }
}

Canvas's method is used to draw geometric figures in the program above, and the second code of the program has not set up Paint brush to use gradient and shadow, so the next geometric figures will be filled with gradient and have shadow. Using an Activity to display the MyView class above, the running program will see the effect shown in the following figure:

Android's Canvas not only draws this simple geometry, but also draws a Bitmap directly, which gives developers great flexibility.

Posted by dross613 on Tue, 25 Jun 2019 15:10:12 -0700