Target:
Draws the Chinese character to the center of the target rectangle.
Questions:
Android Canvas drawing, origin in the DrawText is based on baseline, directly to the target rectangle bottom into DrawText, the character position will be lower. Write the code like this:
[Java]View Plaincopy
- @Override
- Public void OnDraw (canvas canvas) {
- Rect targetrect = new rect ( 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);
- }
Will get ugly results:
Find a solution:
First do your own experiment, set a baseline, and then put the text, and then draw a few lines on the FontMetrics. The FontMetrics is a font pattern, with a float type and an int version, which can be obtained from the paint. Each of its member values is calculated as a baseline, so a negative value is represented above the baseline. Experiment Code:
[Java]View Plaincopy
- @Override
- Public 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);
- //Feel free to set a position as baseline
- int x = 200;
- int y = 400;
- //Draw teststring on the baseline
- Canvas.drawtext (teststring, x, y, paint);
- //BOUNDS1
- Paint.setstyle (Style.stroke); //Draw Hollow Rectangle
- Canvas.save ();
- Canvas.translate (x, y); //Note there are translate here. Gettextbounds The resulting rectangle is also based on the baseline
- Paint.setcolor (Color.green);
- Canvas.drawrect (BOUNDS1, paint);
- Canvas.restore ();
- //Bounds2
- Canvas.save ();
- Paint.setcolor (Color.magenta);
- Canvas.translate (x, y);
- Canvas.drawrect (bounds2, paint);
- Canvas.restore ();
- //Baseline
- Paint.setcolor (color.red);
- Canvas.drawline (x, Y, 1024x768, y, paint);
- //Ascent
- Paint.setcolor (Color.yellow);
- Canvas.drawline (x, Y+fmi.ascent, 1024x768, y+fmi.ascent, paint);
- //Descent
- Paint.setcolor (Color.Blue);
- Canvas.drawline (x, Y+fmi.descent, 1024x768, y+fmi.descent, paint);
- //Top
- Paint.setcolor (Color.dkgray);
- Canvas.drawline (x, Y+fmi.top, 1024x768, y+fmi.top, paint);
- //Bottom
- Paint.setcolor (Color.green);
- Canvas.drawline (x, Y+fmi.bottom, 1024x768, y+fmi.bottom, paint);
- }
Get results:
Red Line is baseline, the top gray line is fontmetrics.top, the bottom of the Green Line is fontmetrics.bottom. (The green bottom and the blue descent are very close)
The character itself is centered between the Gray line and the Green Line , knowing that this is a good idea. Online said the use of Paint.gettextbounds methods are not reliable, you can see a "test" word and 6 words to get the bounds is different, the diagram of the rectangle can be very good to indicate that the function is the boundary of the character, not the font boundaries.
The Fontmetrics.top value is a negative number whose absolute value is the distance the font draws the boundary to baseline.
So if the text is drawn in a rectangle with a fontmetrics height, the DrawText should pass in the-fontmetrics.top.
To draw the center position of the Targetrect, the baseline formula is:
Targetrect.top + (Targetrect.bottom-targetrect.top)/2-(fontmetrics.bottom-fontmetrics.top)/2-fontmetrics.top
Solution:
So the initial code should be changed (by adding the horizontal center):
[Java]View Plaincopy
- @Override
- Public void OnDraw (canvas canvas) {
- Rect targetrect = new rect ( 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 ();
- //Reprint Please specify Source: http://blog.csdn.net/hursing
- int baseline = Targetrect.top + (Targetrect.bottom-targetrect.top-fontmetrics.bottom + fontmetrics.top)/ 2- Fontmetrics.top;
- //below this line is to achieve the horizontal center, drawtext corresponding to the incoming Targetrect.centerx ()
- Paint.settextalign (Paint.Align.CENTER);
- Canvas.drawtext (TestString, Targetrect.centerx (), baseline, paint);
- }
Effect (click to view larger image):
can also go to see the Android SDK source code,
$android 4.2/frameworks/base/corej/ava/android/text/boringlayout.java is an algorithm of TextView drawing text
Reprint Please specify source: http://blog.csdn.net/hursing
Android Canvas DrawText for vertical centering in Chinese