Android Canvas drawText enables vertical center of Chinese Characters

Source: Internet
Author: User

Objectives:

Draw Chinese characters to the center of the target rectangle.

Problem:

In the Canvas drawing of Android, the origin in drawText is baseline and is directly transmitted to drawText based on the bottom of the target rectangle. The character position is down. Write the Code as follows:

@ Overridepublic void onDraw (Canvas canvas) {Rect targetRect = new Rect (50, 50,100 0, 200); Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); paint. setStrokeWidth (3); paint. setTextSize (80); String testString = "test: ijkJQKA: 1234"; paint. setColor (Color. CYAN); canvas. drawRect (targetRect, paint); paint. setColor (Color. RED); canvas. drawText (testString, targetRect. left, targetRect. bottom, paint );}
The following is an ugly result:


Find a solution:

First, let's do the experiment by hand, set a baseline, draw the text, and draw several lines of FontMetrics. FontMetrics contains the font pattern information, including float and int versions, which can be obtained from the Paint. Each of its member values is calculated based on baseline, so the negative value is above baseline. Lab code:

@ Overridepublic void onDraw (Canvas canvas) {Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); paint. setStrokeWidth (3); paint. setTextSize (80); FontMetricsInt fmi = paint. getFontMetricsInt (); String testString = "test: ijkJQKA: 1234"; Rect bounds1 = new Rect (); paint. getTextBounds ("test", 0, 1, bounds1); Rect bounds2 = new Rect (); paint. getTextBounds ("test: ijk", 0, 6, bounds2); // set a random position as baselineint x = 200; int y = 4 00; // draw testString on baseline canvas. drawText (testString, x, y, paint); // bounds1paint. setStyle (Style. STROKE); // draw a hollow rectangular canvas. save (); canvas. translate (x, y); // note that there is translate here. The rectangle obtained by getTextBounds is also the baseline-based paint. setColor (Color. GREEN); canvas. drawRect (bounds1, paint); canvas. restore (); // bounds2canvas. save (); paint. setColor (Color. MAGENTA); canvas. translate (x, y); canvas. drawRect (bounds2, paint); canvas. restore (); // baselinepaint. setColor (Color. RED); canvas. drawLine (x, y, 1024, y, paint); // ascentpaint. setColor (Color. YELLOW); canvas. drawLine (x, y + fmi. ascent, 1024, y + fmi. ascent, paint); // descentpaint. setColor (Color. BLUE); canvas. drawLine (x, y + fmi. descent, 1024, y + fmi. descent, paint); // toppaint. setColor (Color. DKGRAY); canvas. drawLine (x, y + fmi. top, 1024, y + fmi. top, paint); // bottompaint. setColor (Color. GREEN); canvas. drawLine (x, y + fmi. bottom, 1024, y + fmi. bottom, paint );}
Result:


The red line is baseline, the top gray line is FontMetrics. top, and the bottom green line is FontMetrics. bottom. (The green bottom and the blue descent are very close)

Yes,The character itself is centered between the gray line and the Green LineYou can understand this. Use paint. the getTextBounds method is unreliable. You can see that the bounds obtained from a "test" word and six words are different, the rectangle in the figure can represent the character boundary of the function, rather than the font boundary.

The FontMetrics. top value is a negative number, and its absolute value is the distance from the character draw boundary to baseline.
Therefore, if you want to draw text in a FontMetrics height rectangle, drawText should be passed in-FontMetrics. top.
The baseline calculation formula is as follows:

TargetRect. top + (targetRect. bottom-targetRect. top)/2-(FontMetrics. bottom-FontMetrics. top)/2-FontMetrics. top

Solution:

So the initial code should be changed to (by the way, the horizontal center should be added ):

@ Overridepublic void onDraw (Canvas canvas) {Rect targetRect = new Rect (50, 50,100 0, 200); Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); paint. setStrokeWidth (3); paint. setTextSize (80); String testString = "test: ijkJQKA: 1234"; paint. setColor (Color. CYAN); canvas. drawRect (targetRect, paint); paint. setColor (Color. RED); FontMetricsInt fontMetrics = paint. getFontMetricsInt (); // reprinted please indicate the source: http://blog.csdn.net/hursingint baseline = targetRect. top + (targetRect. bottom-targetRect. top-fontMetrics. bottom + fontMetrics. top)/2-fontMetrics. top; // The following row is horizontally centered. The drawText field is changed to targetRect. centerX () paint. setTextAlign (Paint. align. CENTER); canvas. drawText (testString, targetRect. centerX (), baseline, paint );}
Effect (click to view the chart ):

Source code,

$ Android4.2/frameworks/base/corej/ava/android/text/BoringLayout. java is the TextView text painting algorithm.

Reprinted please indicate the source: http://blog.csdn.net/hursing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.