Android Custom Draw 1-1 Plus

The last article was written watching the video of the throwing line. After writing and playing, I found that his article still has a lot of content. Awkward.

Then write chant.

4 levels of custom drawing knowledge

1. DrawXXX() series methods of Canvas and some common methods of Paint class.

The drawXXX() of canvas is the most basic operation of custom drawing. Only after mastering these methods can we know how to draw content. For example, how to draw a circle, how to draw a square, how to draw text. These contents, combined with some common methods of Paint to simply configure the color and style of the drawn content, can meet most of the drawing needs.

2. A Complete Guide to Paint

Paint can do more than just set the color, shadow, thickness. The styles it can do are really huge and very detailed. Such as bilinear filtering, corner shapes, special effects.

3. Canvas's assistance in drawing--range cutting and geometric changes.

Most of the time, they're not used, but when they are, they're cool features.

In the future, don't be afraid of the cool features designed by the designer.

4. Use different drawing methods to control the drawing order.

 Some people say that I need to add a few more views for the drawing order, but this usually has performance problems. So what we solve with the drawing order is the performance problem. Because of the drawing order, one view can do it.

The content of the first series, the most basic use of canvas.drawXXX and paint.

1. The beginning of everything onDraw()

If you master the methods of drawXXX() series and the basics of Paint, you will be able to meet simple drawing needs. They mainly include:

1. All draw methods under the Canvas class. For example drawCircle(), drawBitmap()

2. Several common methods of the Pain class, such as:

paint.style painting mode
paint.color set the paint color
paint.strokeWidth set the stroke width
paint.isAntiAlias ​​anti-aliasing switch

Canvas.drawColor color fill

This is the most basic drawXXX method, which is to uniformly paint the specified color in the entire drawing area.

canvas.drawColor(resources.getColor(R.color.black))

This will directly turn the drawing area black.

Masks can also be set via transparency.

 Similar to drawRGB and drawARGB, the effect is the same.

This type of color filling method is generally used to set the base color before drawing, or set a translucent mask after drawing.

drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

The first two parameters are the coordinates of the center of the circle. The third is the radius of the circle. Together they constitute the basic information of the circle. The fourth parameter is Paint. It provides all style information except basic information.

In Android, each View has its own coordinate system. are not affected by each other. The origin of the coordinate system is the point in the upper left corner of the View. So when we set to draw this circle, for example, we set the coordinates of the center of the circle to be 300, 300, then it looks like this:

 If the circle you want to draw is not solid but hollow, you can do this:

paint.style = Paint.Style.STROKE

 Here style has three modes, fill, stroke, fill_and_stroke. These are Fill, Stroke, Fill and Stroke respectively.

You are in stroke and fill_and_stroke mode, you can also set the width of the line:

paint.strokeWidth = 20f

 When drawing, in order to make the edges of graphics and text smoother, it is often necessary to turn on anti-aliasing:

paint.isAntiAlias = true

So anti-aliasing is so good, why not turn it on by default?

In essence, anti-aliasing occurs because the graphics resolution is too low, causing the human eye to perceive the pixel grains in the picture.

So, why does it look smooth when anti-aliasing is turned on? Because the principle of anti-aliasing is to modify the color of the edge of the graphic. And make the graphics look smoother.

 It can be seen that when anti-aliasing is not turned on, the color of all pixels is also black. When turned on, the color of the edge is slightly changed. Therefore, anti-aliasing will cause graphics distortion.

In addition to drawCircle, you can also draw other graphics.

 In addition, he has two other overloaded methods, drawRect(RectF rect, Paint paint) and  drawRect(Rect rect, Paint paint) , which allow you to directly fill in rectF or rect to draw a rectangle.

canvas.drawPoint(50f,50f,paint)

Let's look at this drawPoint again, which is to draw a point, and x and y are the coordinates of the point. The point size can be set by strokeWidth.

The shape of the point can be set by strokeCap.

 In addition to ROUND, strokeCap ​​can also use BUTT, and SQUARE

 A bit like drawCircle and drawRect in FILL mode. The effect is the same, it depends on which one you like.

So why engage in two APIs? Because drawPoint can draw multiple points.

 Here drawPoints is used to pass an array, and every two in this array are a pair of coordinates.

The offset parameter refers to skipping several numbers in the array, and the subsequent count is to draw several points.

 paint.style = Paint.Style.FILL
        paint.strokeWidth = 20f
        canvas.drawOval(50f,50f,300f,200f,paint)

paint.style = Paint.Style.STROKE下:

In addition, he has an overloaded method, drawOval(rect:RectF,paint) can also use RectF to draw.

Lines can be drawn using drawLine:

canvas.drawLine(50f,50f,200f,500f,paint)

 Because this is not a closed graph directly, the style has no effect on it.

It is also possible to draw multiple points via drawLines. That is, a copy of drawLine.

val floatArray = floatArrayOf(20f,20f,50f,50f,100f,100f,120f,300f,200f,400f,200f,100f)
canvas.drawLines(floatArray,paint)

 Next, look at drawRoundRect, which is a rectangle with rounded corners.

canvas.drawRoundRect(100f,100f,200f,200f,10f,10f,paint)

Next, look at drawArc again. This is for drawing arcs or sectors.

drawArc uses an ellipse to describe an arc.

paint.style = Paint.Style.STROKE
canvas.drawArc(100f,100f,200f,200f,-100f,100f,true,paint)

 

First, the first four parameters are the coordinates of the four boundary points of the ellipse, and startAngle is the starting angle of the arc. The positive direction of the X-axis is the position of 0 degrees, the counterclockwise is the negative angle, and the clockwise is the positive angle. sweepAngle is the angle at which the arc is swept. Note that the sweep here refers to the clockwise sweep at the starting angle. userCenter indicates whether the starting radian and the end position after swipe are connected to the center point. If it's connected, it's an arc. If it's not connected, it's scalloped.

canvas.drawArc(100f,100f,200f,200f,-100f,100f,false,paint)

 

 Let's look at the fill mode again.

paint.style = Paint.Style.FILL
canvas.drawArc(100f,100f,200f,200f,-100f,100f,true,paint)

paint.style = Paint.Style.FILL
canvas.drawArc(100f,100f,200f,200f,-100f,100f,false,paint)

 

 The above is all the simple graphics drawing of cavans. In addition to simple graphics drawing, you can also use path to draw complex custom graphics.

 drawPath(Path path,Paint paint)

This method is a bit complicated.

The methods mentioned above all draw the given graphics. And drawPath can draw custom graphics. This method is used for graffiti boards.

The path here is to describe the path object.

For example, to draw a heart shape:

Path can describe straight lines, quadratic curves, cubic curves, circles, ellipses, rectangles, arcs, and rounded rectangles. By combining these graphics, you can draw many complex graphics.

Path has two types of methods, one is to directly describe the path, and the other is auxiliary setting or calculation.

 The first method of Path: directly describe the path

This type of method can be further subdivided into 2 groups: adding subgraphs and drawing lines (straight lines or curves)

The first group: addXXx --- add sub-graphics

addCircle(float x, float y, float radius, Direction dir)

add circle

The first three parameters are the basic information of the circle, and the last parameter is the direction of the circle's path.

But for normal cases, fill in counterclockwise or clockwise. No effect. We generally need to choose to fill graphics or stroke.

And when the graphics intersect, we need to judge the filling range. for example:

 

After using Path.addCircle to add a circle, you can use canvas.drawPath to draw it.

path.addCircle(300f,300f,200f,Path.Direction.CW)
        canvas.drawPath(path,paint)

 In addition to addCircle, there are other addOval, add ellipse, addRect add rectangle, addRoundRect add rounded rectangle, addPath(path) add another path.

The usage of the above methods is similar to that of addCircle.

The second group of methods: xxxTo()-----draw a line (straight line or curve)

The difference with the first group of methods is that the first group is to add a complete closed figure (except addPath), this group just adds a line.

lineTo(float x, float y)/ rLineTo(floatx, float y) draw a straight line

Draw a straight line from the current position to the target position. xy are the coordinates of the target location. The difference between these two methods is that the parameters of lineTo are absolute targets, while the parameters of rLineTo are relative coordinates relative to the current position. The prefix r means relative, relative.

Current position: The so-called current position refers to the end position of the last call to draw the Path method. The initial value is the origin (0,0)

paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.rLineTo(100f,0f) //由当前位置(0,0)向正右方100像素的位置画一条直线
        canvas.drawPath(path,paint)

quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) draw quadratic Bezier curve

The starting point of this Bezier curve is the current position, and the x1, y1, x2, and y2 in the parameters are the coordinates of the control point and the end point, respectively.

cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) draw cubic Bezier curve

Same as the quadratic Bezier curve above

moveTo(float x, float y)/ rMoveTo(float x, float y) moves to the target position

Whether it is a straight line or a Serre curve, the current position is used as the starting point, and the starting point cannot be specified. But we can change the current position through moveTo(x, y) or rMoveTo(x, y), so as to indirectly set the starting point of these methods.

 paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.moveTo(200f,100f)//移动
        path.lineTo(200f,0f)//画竖线
        canvas.drawPath(path,paint)

 Although moveTo cannot add graphics, it can set the starting point. So this is a very important helper method.

arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle)画弧形

This method is compared with canvas.drawArc. There is one less parameter useCenter, but one more parameter, forceMoveTo.

Why is this so? Because arcTo is only used to draw arcs, not fans. So this parameter is useless.

So what does this forceMoveTo mean?

When drawing, do you lift the pen or drag the handwriting over. The difference is whether to leave traces of movement.

paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.arcTo(100f,100f,300f,300f,-90f,90f,true) //强制移动到弧形起点(无痕迹)
        canvas.drawPath(path,paint)

path.arcTo(100f,100f,300f,300f,-90f,90f,false) //leave traces

 

addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)

This is again an arc method. One addArc, one arcTo, what's the difference?

In fact, it is very simple. There is one parameter forceMoveTo missing here, which defaults to true.

close() closes the current subgraphic

What is closed, is to draw a line from the current position to the starting point of the current sub-graph.

First look at the ones that are not closed:

 paint.style = Paint.Style.STROKE
        path.moveTo(100f,100f)
        path.lineTo(200f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.lineTo(150f,150f)

What if we close it at this time?

paint.style = Paint.Style.STROKE
        path.moveTo(100f,100f)
        path.lineTo(200f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.lineTo(150f,150f)
        path.close()

 

 You may think that at this time, it is also possible to use the lineTo starting point. Yes, it is completely equivalent to Lineto at this time.

The so-called sub-graph is an uninterrupted connection.

In addition, when the style is fill or fill_and_stroke, it will be automatically connected.

The second type of Path method: auxiliary setting or calculation.

There are relatively few usage scenarios for this type of method. You don't have to learn too much. Only one of the more commonly used ones in the semester:

setFillType(FillType fillType)

As mentioned earlier, path.setFillType is used to set the filling algorithm when the graph self-intersects.

There are 4 values ​​of FillType:

1.EVEN_ODD

2. WINDING default value

3.INVERSE_EVEN_ODD

4.INVERSE_WINDING

The two prefixed with INVERSE are the inverted versions of 1 and 2.

WINDING is full fill, EVEN_ODD is cross fill.

This is a simple and crude version, which is usually the case.

drawBitmap(Bitmap bitmap, float left, float top, Paint paint)画Bitmap

Draw the Bitmap object, mid-term left, top are the position coordinates where the bitmap is to be drawn.

drawText(String text, float x, float y, Paint paint) draw text

All displayed content in the interface is drawn, including text. The drawText method is to draw text.

The parameter text is the string used to draw, and x, y are the coordinates of the starting point of drawing.

Guess you like

Origin blog.csdn.net/howlaa/article/details/128719408