One, Customize View Foundation:
1, Brush Paint
Text correlation:
Method | describe |
---|---|
setColor(@ColorInt int color) | setpc |
setStrokeWidth(float width) | Set Brush Thickness |
setTextSkewX(float f) | Set slant, negative right slant, positive left |
setARGB(int a, int r, int g, int b) | Set color, a for transparency |
setTextSize(float textSize) | Set Drawing Text Size |
setFakeBoldText(boolean fakeBoldText) | Bold or not |
setTextAlign(Paint.Align align) | Set text alignment, LEFT, CENTER, RIGHT |
setUnderlineText(boolean underlineText) | Set Underline |
setStyle(Style style) | Set Brush Style, FILL, STROKE, FILL_ AND_ STROKE setTypeface |
Bitmap correlation
Method | describe |
---|---|
setDither(boolean dither) | Set up jitter handling |
setAlpha(int a) | Set Transparency |
setAntiAlias(boolean aa) | Whether to turn on anti-aliasing |
setFilterBitmap() | Whether to turn on optimized Bitmap |
setColorFilter(ColorFilter filter) | Set up color filtering |
setMaskFilter(MaskFilter maskfilter) | Set up the effect of the filter |
setShader(Shader shader) | Set image gradient effect |
setStrokeJoin(Paint.Join join) | Set Image Combination |
setXfermode(Xfermode xfermode) | Set Image Overlay Effect |
setPathEffect(PathEffect effect) | Set path effect reset() to restore default settings |
2, Path
moveTo() Draw the starting point lineTo() Draw connected points close() Form a closed loop
arcTo() arc path
Parameters: Rectangle to generate ellipse, angle to start arc, angle to scan arc, whether to force the start point of arc to be the starting point of drawing
Region region: An arbitrary-shaped enclosed graphic. Use RegionIterator for region intersection filling operations.
3, Canvas
1) Clear the canvas
/** * Canvas Clearing Screen */ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
2) Draw the canvas background
/** * Draw canvas background */ //Draw canvas background, argb canvas.drawARGB(99, 255, 0, 255); canvas.drawRGB(255, 0, 255); canvas.drawColor(Color.LTGRAY);
3) Draw a circle
/** * Draw a circle */ //Setting the basic properties of a brush //setpc mPaint.setColor(Color.RED); //Set Brush Fill Style //Fill Inside Only mPaint.setStyle(Paint.Style.FILL); //Fill in interior and stroke mPaint.setStyle(Paint.Style.FILL_AND_STROKE); //Fill only the stroke mPaint.setStyle(Paint.Style.STROKE); //Sets the stroke width in px, which is valid when the fill style is FILL_AND_STROKE mPaint.setStrokeWidth(20); //Use canvas to draw circles canvas.drawCircle(200, 200, 150, mPaint); mPaint.setColor(Color.BLUE); canvas.drawCircle(200, 200, 130, mPaint);
4) Draw Points
/** * Draw Points */ //Size of points mPaint.setStrokeWidth(20); //Draw point, x-coordinate, y-coordinate canvas.drawPoint(340, 340, mPaint);
5) Draw straight lines
/** * draw a straight line */ //Line thickness mPaint.setStrokeWidth(20); //Draw line starting x-coordinate, starting y-coordinate, ending x-coordinate, ending y-coordinate canvas.drawLine(360, 360, 660, 660, mPaint);
6) Drawing
/** * draw rectangle */ //Border thickness of rectangle mPaint.setStrokeWidth(5); //Fill rectangular stroke only mPaint.setStyle(Paint.Style.STROKE); //Draw a rectangle, RectF is a rectangle to hold float type, Rect is a rectangle to hold int type, top left and bottom right mRectF.set(400F, 400F, 450F, 450F); mRect.set(500, 500, 550, 550); canvas.drawRect(mRectF, mPaint); canvas.drawRect(mRect, mPaint);
7) Drawing Text
/** * Draw Text * setColor(@ColorInt int color) setpc * setStrokeWidth(float width) Set Brush Thickness * setTextSkewX(float f) Set slant, negative right slant, positive left * setARGB(int a, int r, int g, int b) Set color, a for transparency * setTextSize(float textSize) Set Drawing Text Size * setFakeBoldText(boolean fakeBoldText) Bold or not * setTextAlign(Paint.Align align) Set text alignment, LEFT, CENTER, RIGHT setUnderlineText(boolean underlineText) Set underline * setStyle(Style style) Set Brush Style, FILL, STROKE, FILL_AND_STROKE setTypeface(Typeface typeface) sets the Typeface object, i.e. font style, including bold, italic, serif, non-serif, etc. */ mPaint.setTextSize(90f); canvas.drawText("Android Stack", 200, 1000, mPaint);
2. Drawing Text
Prepare the base class BaseView and inherit the View class.
public class BaseView extends View { static final int LINE_OFFSET = 60; protected Paint notePaint = new Paint(); protected Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); protected Rect textRect = new Rect(); public BaseView(Context context) { this(context, null); } public BaseView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
Two brushes are prepared in BaseView.
The method of drawing text, canvas.drawText, requires specifying a string, drawing the starting coordinates, and paint ing the brush.
canvas.drawText(text, x, y, textPaint);
The horizontal line along which the y-value of the starting coordinate is located is also called baseline.
Getting Text Boundaries
You can see from the picture that part of the stroke of the text can go beyond the edge line. Like the j at the beginning.
Use the Paint.getTextBounds method to get the boundaries of the text.
textPaint.getTextBounds(onShowText, 0, onShowText.length(), textRect); // Get text Boundary
Draw part of the code above
private void drawBounds(Canvas canvas, float tx, float ty, String onShowText) { canvas.drawText(onShowText, tx, ty, textPaint); // Write textPaint.getTextBounds(onShowText, 0, onShowText.length(), textRect); // Get text Boundary notePaint.setStrokeWidth(3); notePaint.setColor(Color.parseColor("#EF6C00")); // Left Side Line canvas.drawLine(tx, ty - textRect.height() - LINE_OFFSET, tx, ty + LINE_OFFSET, notePaint); // Right Side Line canvas.drawLine(tx + textRect.width(), ty - textRect.height() - LINE_OFFSET, tx + textRect.width(), ty + LINE_OFFSET, notePaint); notePaint.setColor(Color.parseColor("#FF0277BD")); // Upper Line canvas.drawLine(tx - LINE_OFFSET, ty - textRect.height(), tx + textRect.width() + LINE_OFFSET, ty - textRect.height(), notePaint); notePaint.setColor(Color.parseColor("#00695C")); // y - baseline canvas.drawLine(tx - LINE_OFFSET, ty, tx + textRect.width() + LINE_OFFSET, ty, notePaint); }
Get text size information
The Paint.FontMetrics class is required. It has five properties
attribute | introduce |
---|---|
top | Maximum distance from baseline to top of highest text |
ascent | Recommended distance of space above baseline when singled spaced |
descent | Recommended distance of space below baseline when one-line spacing |
bottom | Maximum distance from baseline to the lowest character |
leading | Additional space recommended between lines of text |
Get Paint.FontMetrics using the Paint.getFontMetrics() method.
Paint.FontMetrics fm = textPaint.getFontMetrics();
Note that top and ascent are negative values.
Method of drawing the above diagram
private void drawFontMetrics(Canvas canvas, float x, float y, String text) { canvas.drawText(text, x, y, textPaint); textPaint.getTextBounds(text, 0, text.length(), textRect); Paint.FontMetrics fm = textPaint.getFontMetrics(); notePaint.setStrokeWidth(1); notePaint.setColor(Color.BLACK); canvas.drawText(String.format(Locale.CHINA, "top:%.2f, bottom:%.2f", fm.top, fm.bottom), x, y + notePaint.getTextSize() * 2.5f, notePaint); canvas.drawText(String.format(Locale.CHINA, "ascent:%.2f, descent:%.2f, leading:%.2f", fm.ascent, fm.descent, fm.leading), x, y + notePaint.getTextSize() * 4f, notePaint); notePaint.setColor(Color.parseColor("#FFD84315")); // fm top line canvas.drawLine(x - L_BIAS, y + fm.top, x + textRect.width() + L_BIAS, y + fm.top, notePaint); notePaint.setColor(Color.parseColor("#FF00695C")); // fm bottom line canvas.drawLine(x - L_BIAS, y + fm.bottom, x + textRect.width() + L_BIAS, y + fm.bottom, notePaint); notePaint.setColor(Color.parseColor("#4527A0")); // fm ascent line canvas.drawLine(x - L_BIAS, y + fm.ascent, x + textRect.width() + L_BIAS, y + fm.ascent, notePaint); notePaint.setColor(Color.parseColor("#0E0822")); // fm descent line canvas.drawLine(x - L_BIAS, y + fm.descent, x + textRect.width() + L_BIAS, y + fm.descent, notePaint); }
Align text in the middle
With this foundation, we can quickly learn how to achieve text "center alignment". Align horizontal or vertical centerlines of text to a point.
For example, draw a planar coordinate system
Draw two axes, then draw the scale and write the value. The numeric text corresponds to the location of the scale. We mainly use Paint.getTextBounds to get the size information of the text and then calculate the appropriate location.
private void drawChart(Canvas canvas) { final float x0 = 100; final float y0 = 300; // The coordinates of the origin on the canvas final float halfLine = 5; // Half the length of the scale textPaint.setColor(Color.BLACK); textPaint.setTextSize(20); notePaint.setStrokeWidth(2); canvas.drawLine(x0, y0, x0 + 500, y0, notePaint); // Draw the horizontal axis canvas.drawLine(x0, y0, x0, y0 - 290, notePaint); // Draw Vertical Axis // Draw horizontal scales and numbers for (int i = 1; i <= 4; i++) { int step = i * 100; String n = String.valueOf(step); float x = x0 + step; canvas.drawLine(x, y0 - halfLine, x, y0 + halfLine, notePaint); // scale // Text alignment textPaint.getTextBounds(n, 0, n.length(), textRect); canvas.drawText(n, x - textRect.width() / 2f, y0 + textRect.height() + halfLine, textPaint); } // Draw Vertical Scales and Numbers for (int i = 1; i <= 2; i++) { int step = i * 100; String n = String.valueOf(step); float y = y0 - step; canvas.drawLine(x0 - halfLine, y, x0 + halfLine, y, notePaint); // scale // Text alignment textPaint.getTextBounds(n, 0, n.length(), textRect); canvas.drawText(n, x0 - halfLine * 2 - textRect.width(), y + textRect.height() / 2f, textPaint); } // Draw Origin 0 String origin = "0"; textPaint.getTextBounds(origin, 0, origin.length(), textRect); canvas.drawText(origin, x0 - textRect.width(), y0 + textRect.height(), textPaint); }
Three, clip the canvas clip path
Use the canvas.clipPath(path) method.
The clipPath method is equivalent to clipping the canvas along a given path. For this purpose, we can make rounded pictures.
Rounded Picture Example
Rounded pictures are a common design. There is no direct way to display rounded pictures in the official Android library. If it's a solid, gradient background, we can use corners of shape s to round corners. This is where clipPath cuts out rounded corners of the canvas before super.onDraw(canvas). A Path needs to be passed in to specify the clipping range.
Create a new RoundImageView class that inherits from AppCompatImageView.
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Path; import android.util.AttributeSet; import androidx.appcompat.widget.AppCompatImageView; public class RoundImageView extends AppCompatImageView { private float vw, vh; private Path path = new Path(); private float topLeftR; private float topRightR; private float botLeftR; private float botRightR; public RoundImageView(Context context) { this(context, null); } public RoundImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView); topLeftR = typedArray.getDimensionPixelSize(R.styleable.RoundImageView_topLeftR, 0); topRightR = typedArray.getDimensionPixelSize(R.styleable.RoundImageView_topRightR, 0); botLeftR = typedArray.getDimensionPixelSize(R.styleable.RoundImageView_botLeftR, 0); botRightR = typedArray.getDimensionPixelSize(R.styleable.RoundImageView_botRightR, 0); typedArray.recycle(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); vw = getWidth(); vh = getHeight(); } @Override protected void onDraw(Canvas canvas) { path.reset(); if (vw > topLeftR && vh > topRightR) { path.moveTo(topLeftR, 0); path.lineTo(vw - topRightR, 0); path.quadTo(vw, 0, vw, topRightR); path.lineTo(vw, vh - botRightR); path.quadTo(vw, vh, vw - botRightR, vh); path.lineTo(botLeftR, vh); path.quadTo(0, vh, 0, vh - botLeftR); path.lineTo(0, topLeftR); path.quadTo(0, 0, topLeftR, 0); path.close(); canvas.clipPath(path); } super.onDraw(canvas); } }
TypedArray is used and declare-styleable resources need to be added.
<resources> <declare-styleable name="RoundImageView"> <attr name="topLeftR" format="dimension" /> <attr name="topRightR" format="dimension" /> <attr name="botLeftR" format="dimension" /> <attr name="botRightR" format="dimension" /> </declare-styleable> </resources>
Use this class. Use directly in layout. Four fillet radius parameters are defined. Set solid color for src. Given a picture, the fillet effect is only visible when the picture content touches the view endpoint.
<com.rustfisher.tutorial2020.customview.view.RoundImageView style="@style/RoundIvCube" app:botLeftR="8dp" app:botRightR="8dp" app:topLeftR="8dp" app:topRightR="8dp" /> <com.rustfisher.tutorial2020.customview.view.RoundImageView style="@style/RoundIvCube" app:botLeftR="25dp" app:botRightR="25dp" app:topLeftR="25dp" app:topRightR="25dp" /> <com.rustfisher.tutorial2020.customview.view.RoundImageView style="@style/RoundIvCube" app:botLeftR="16dp" /> <com.rustfisher.tutorial2020.customview.view.RoundImageView style="@style/RoundIvCube" app:topLeftR="16dp" /> <com.rustfisher.tutorial2020.customview.view.RoundImageView style="@style/RoundIvCube" app:botRightR="16dp" app:topLeftR="16dp" />
style definition
<style name="RoundIvCube"> <item name="android:layout_width">50dp</item> <item name="android:layout_height">50dp</item> <item name="android:src">#303F9F</item> <item name="android:layout_margin">8dp</item> </style>
Run Results
You can see the rounded corners of each graphic. But we can also see jagged teeth. This clipping method does not make smooth rounded corners.