Use canvas and Paint to draw text in the center of the View, canvaspaint
This blog is original as long as it does not indicate "Conversion". For the post, please indicate the link to this blog.
In custom views, we sometimes want to draw the text by ourselves. When we draw the text by ourselves, we usually want to precisely locate the text, and the text Center (horizontal and vertical) is a common requirement, so here we take the text center as an example to see how the text in android should be drawn. What is the difference between it and Java.
Let's take a look at our goals.
I opened the screenshot after "display layout boundary", and there are many boxes.
Observe the text area carefully and we will findThere are 5 lines of different colors in the text area.. PressFrom top to bottomTheir names are:
Top: light gray
Ascent: Yellow
Baseline: red
Descent: Blue
Bottom: Green
What are the five lines? Android development documentation has been explained.
Top |
The maximum distance abve the baseline for the tallest glyph in the font at a given text size. |
Ascent |
The recommended distance abve the baseline for singled spaced text. |
Leading |
The recommended additional space to add between lines of text. |
Descent |
The recommended distance below the baseline for singled spaced text. |
Bottom |
The maximum distance below the baseline for the lowest glyph in the font at a given text size. |
Let's start with a question.
If you try to arrange up and down two textviews without margin and padding, you will surely find that there is still a gap between the two TextView texts. First, set includeFontPadding to false! However, there is still a gap. The gap is caused by the gap between top and ascent and the gap between bottom and descent.
The position of the five lines is determined by the font and font size used. Paint provides a way to obtain the positions of the above five lines.
Generally, we use characters between ascent and descent, so we can center the part between ascent and descent to our View.
Baseline is used as the benchmark, and the value is negative upward and positive downward. Ascent is a negative number, and descent is a positive number.
The total coordinate in drawText in the Canvas is baseline, so we need to calculate the baseline position first.
Baseline = (mHeight-(mFontMetricsInt. descent-mFontMetricsInt. ascent)/2-mFontMetricsInt. ascent
This ensures that the distance between the upper margin and the bottom margin of the View from the ascent is the same as that from the descent to the View. This distance plus the absolute value of the ascent (-ascent) is the location of the baseline.
Private void init () {mPaint = new Paint (Paint. ANTI_ALIAS_FLAG); mPaint. setStrokeWidth (3); mPaint. setTextSize (60); mPaint. setTextAlign (Paint. align. CENTER); mPaint. setStyle (Paint. style. STROKE); mFontMetricsInt = mPaint. getFontMetricsInt () ;}@ Overridepublic void onDraw (Canvas canvas) {int x; if (mPaint. getTextAlign () = Paint. align. LEFT) {// LEFT x = mWidth/2-(int) (mStringWidth/2);} else if (mPaint. getTextAlign () = Paint. align. CENTER) {// medium x = mWidth/2;} else {// right x = mWidth/2 + (int) (mStringWidth/2 );} int xFrom = mWidth/2-(int) (mStringWidth/2); int xTo = mWidth/2 + (int) (mStringWidth/2 ); // baseline = (mHeight-(mFontMetricsInt. descent-mFontMetricsInt. ascent)/2-mFontMetricsInt. ascent // baseline = (mHeight-mFontMetricsInt. ascent-mFontMetricsInt. descent)/2 int y = (mHeight-mFontMetricsInt. ascent-mFontMetricsInt. descent)/2; Log. d (TAG, "ascent:" + mFontMetricsInt. ascent); Log. d (TAG, "descent:" + mFontMetricsInt. descent); Log. d (TAG, "top:" + mFontMetricsInt. top); Log. d (TAG, "bottom:" + mFontMetricsInt. bottom); Log. d (TAG, "baseline:" + y); // baseline mPaint. setColor (Color. RED); canvas. drawLine (xFrom, y, xTo, y, mPaint); // ascent mPaint. setColor (Color. YELLOW); canvas. drawLine (xFrom, y + mFontMetricsInt. ascent, xTo, y + mFontMetricsInt. ascent, mPaint); // descent mPaint. setColor (Color. BLUE); canvas. drawLine (xFrom, y + mFontMetricsInt. descent, xTo, y + mFontMetricsInt. descent, mPaint); // top mPaint. setColor (Color. LTGRAY); canvas. drawLine (xFrom, y + mFontMetricsInt. top, xTo, y + mFontMetricsInt. top, mPaint); // bottom mPaint. setColor (Color. GREEN); canvas. drawLine (xFrom, y + mFontMetricsInt. bottom, xTo, y + mFontMetricsInt. bottom, mPaint); mPaint. setColor (Color. BLACK); canvas. drawText (TEST_STRING, x, y, mPaint) ;}@ Overrideprotected void onSizeChanged (int w, int h, int oldw, int oldh) {super. onSizeChanged (w, h, oldw, oldh); mWidth = w; mHeight = h;} private int mWidth; private int mHeight; private float mStringWidth; private float measureText () {mStringWidth = mPaint. measureText (TEST_STRING); return mStringWidth ;}
Note: The positions of the above lines are related to the font.For example, when you use "正 ", you will find that top and ascent overlap.
Private void init () {mTf = Typeface. createFromAsset (mContext. getAssets (), "fzyt. ttf "); mPaint = new Paint (Paint. ANTI_ALIAS_FLAG); mPaint. setTypeface (mTf); mPaint. setStrokeWidth (3); mPaint. setTextSize (60); mPaint. setTextAlign (Paint. align. CENTER); mPaint. setStyle (Paint. style. STROKE); // draw a hollow rectangle mFontMetricsInt = mPaint. getFontMetricsInt (); Log. d (TAG, "measureText:" + measureText ());}
The vertical center solution makes it easy to center horizontally. Because ...... You can set it directly in Paint.
mPaint.setTextAlign(Paint.Align.CENTER);
Of course, the method here is only left-right. Even if the center is not set here, we can also manually center the text.
Int x; if (mPaint. getTextAlign () = Paint. align. LEFT) {// LEFT x = mWidth/2-(int) (mStringWidth/2);} else if (mPaint. getTextAlign () = Paint. align. CENTER) {// medium x = mWidth/2;} else {// right x = mWidth/2 + (int) (mStringWidth/2 );}
After the horizontal and vertical coordinates are calculated, we can use drawText.
canvas.drawText(TEST_STRING, x, y, mPaint);
At this point, all the problems are solved. We know the positions of the lines above the text, and we can place our text at will.
When drawing numbers, 1 is obviously thinner than 4, but we may get the same width, so there is no way to "really center.
Attach the layout file,If you set padding, remember to calculate the padding.
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF"> <com.example.TextTest.TextView android:layout_width="250dip" android:layout_height="100dip" android:layout_marginTop="10dip" android:layout_marginBottom="20dip" android:layout_marginLeft="10dip" android:layout_marginRight="20dip"/></LinearLayout>
Finally, let's take a look at the differences between fonts in Java and Android.
The Font concept in Java is here: Font Concepts. As you can see, there is no concept of top and bottom in Android.
Baseline is also explained in Wikipedia. The concepts of top and bottom in Android are not mentioned here.
Repost the following link
My blog address
Http://su1216.iteye.com/
Http://blog.csdn.net/su1216/
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.