Android自定义控件drawText详解(五)

但行好事,莫问前程。只需努力每一天。

上一篇文章地址

小时候,我们在刚开始学习写字母时,用的本子是四线格的,我们必须把字母按照规则写在四线格内。比如:

那么问题来了,在canvas在利用drawText绘制文字时,也是有规则的,这个规则就是基线!
我们先来看一下什么是基线:


可见基线就是四线格中的第三条线!也就是说,只要基线的位置定了,那文字的位置必然是定了的!

下面我们来重新看看canvas.drawText()这个函数,所有drawText()函数的基本用法,在文章Android 路径及文字(二)中已经讲过,这里就不再一一讲解,只拿出一个来讲解下drawText与基线的关系:

/**
* text:要绘制的文字
* x:绘制原点x坐标
* y:绘制原点y坐标
* paint:用来做画的画笔
*/
public void drawText(String text, float x, float y, Paint paint)

上面这个构造函数是最常用的drawText方法,传进去一个String对象就能画出对应的文字。
但这里有两个参数需要非常注意,表示原点坐标的x和y.很多同学可能会认为,这里传进去的原点参数(x,y)是绘制文字所在矩形的左上角的点。但实际上并不是!比如,我们上面如果要画"Android World Blog"这几个字,这个原点坐标应当是下图中绿色小点的位置


在(x,y)中最让人捉急的是y坐标,一般而言,(x,y)所代表的位置是所画图形对应的矩形的左上角点。但在drawText中是非常例外的,y所代表的是基线的位置!

下面我们就举个例子来看一下drawText中,原点坐标(x,y)的位置。
1、自定义一个MyTextView.java
我们重写onDraw函数,自定义一个基线,然后利用drawText画出来:

package com.as.customview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

import androidx.annotation.Nullable;

public class MyTextView extends View {

    public MyTextView(Context context) {
        this(context, null);
    }

    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int baseLineX = 0;
        int baseLineY = 200;

        //画基线
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);
    }


}

在这里,先定义drawText原点的位置:(0,200),首先,我们把(0,200)所在的这条横线画出来,所以我先画了一条线从点坐标为(0,200)到点坐标为(3000,200)的一条直线,然后利用canvas.drawText以(0,200)为原点画出文字

2、在main.xml中添加使用代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.as.customview.MyTextView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

结论:

  • 1、drawText是中的参数y是基线的位置。
  • 2、一定要清楚的是,只要x坐标、基线位置、文字大小确定以后,文字的位置就是确定的了。

paint.setTextAlign(Paint.Align.XXX);

在上面我们讲了,drawText()函数中的Y坐标表示所要绘制文字的基线所在位置。从上面的例子,我们可以看到,我们绘图结果是在X坐标的右边开始绘制的,但这并不是必然的结果。
我们来看一张图:



我们知道,我们在drawText(text, x, y, paint)中传进去的源点坐标(x,y);其中,y表示的基线的位置。那x代表什么呢?从上面的例子运行结果来看,应当是文字开始绘制的地方。

哈哈,并不是!x代表所要绘制文字所在矩形的相对位置。相对位置就是指(x,y)在所要绘制矩形的位置。我们知道绘制矩形的纵坐标是由Y值来确定的,而相对x坐标的位置,只有左、中、右三个位置了。也就是所绘制矩形可能是在x坐标的左侧绘制,也有可能在x坐标的中间,也有可能在x坐标的右侧。而定义在x坐标所绘制矩形相对位置的函数是:

/**
* 其中Align的取值为:Panit.Align.LEFT,Paint.Align.CENTER,Paint.Align.RIGHT
*/
Paint::setTextAlign(Align align);

我们再来重新看一下上面的例子,当我们设置为不同的值时,绘制结果是怎样的。

在原来代码上加上paint.setTextAlign(Paint.Align.LEFT)

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int baseLineY = 200;
        int baseLineX = 0;

        //画基线
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);
    }

可见,原点(x,y)在矩形的左侧,即矩形从(x,y)的点开始绘制

同样的代码,把相对位置设置为:setTextAlign(Paint.Align.CENTER)

 protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int baseLineY = 200;
        int baseLineX = 0;

        //画基线
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);
    }

所以原点(x,y)就是文字所在矩形区域的正中间,换句话说,系统会根据(x,y)的位置和文字所在矩形大小,会计算出当前开始绘制的点。以使原点(x,y)正好在所要绘制的矩形的正中间。

将相对位置设置为:setTextAlign(Paint.Align.RIGHT)

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int baseLineY = 200;
        int baseLineX = 0;

        //画基线
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.RIGHT);
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);
    }

所以原点(x,y)应当在所要绘制矩形的右侧,在上面的代码中,也就是说整个个矩形都在(0,200)的左侧,所以我们看到的是什么都没有。

注意下面,我们再看一个例子:

我们只写一个大写字母A,然后将其相对位置设置为paint.setTextAlign(Paint.Align.CENTER)


我们可以看到字母A在原点(0,200)的正中间。这也就是我们要强调的:相对位置是根据所要绘制文字所在矩形来计算的。

drawText的四线格与FontMetrics

前面我们讲了基线,其实除了基线,系统在绘制Text时,还是有其它线的,我们来看个图:

除了基线以外,如上图所示,另外还有四条线,分别是ascent,descent,top,bottom,他们的意义分别是:

  • ascent: 系统建议的,绘制单个字符时,字符应当的最高高度所在线
  • descent:系统建议的,绘制单个字符时,字符应当的最低高度所在线
  • top: 可绘制的最高高度所在线
  • bottom: 可绘制的最低高度所在线

单从这几个定义,大家可能还是搞不清这几值到底是什么意义。我们来看一下电视的显示。用过视频处理工具的同学(比如premiere,AE,绘声绘影等),应该都会知道,在制作视频时,视频显示位置都会有一个安全区域框,如下图所示:



如上图所示,黑色部分表示电视屏幕,红色框就表示安全区域框。

这个安全框是用来干嘛的?这个安全框就是系统推荐给我们的显示区域,电视屏幕是每个区域都是可以显示图像的,但由于制式的不同,每个国家的屏幕大小并不一致,当遇到不一致时,就会裁剪。但系统给我们推荐的显示区域是无论哪种制式都是可以完整显示出来的,所以我们在制作视频时,尽量要把要显示的图像放在所推荐的显示区域内。

同样,在这里,我们在绘制文字时,ascent是推荐的绘制文字的最高高度,就表示在绘制文字时,尽力要在这个最高高度以下绘制文字。descent是推荐的绘制文字的最底高度线,同样表示是在绘制文字时尽量在这个descent线以上来绘制文字。而top线则指该文字可以绘制的最高高度线,bottom则是表示该文字可以绘制的最低高度线。ascent,descent是系统建议上的绘制高度,而top,bottom则是物理上屏幕最高,最低可以画的高度值。他们的差别与我们上面说的视频处理的安全框和屏幕的道理是一样的。

FontMetrics概述

上面我们讲了,系统在画文字时的五条线,baseline、ascent、descent、top、bottom我们知道baseline的位置是我们在构造drawText()时的参数y来决定的,那ascent,descent,top,bottom这些线的位置要怎么计算出来呢?
Android给我们提供了一个类:FontMetrics,它里面有四个成员变量:

/**
     * Convenience method for callers that want to have FontMetrics values as
     * integers.
     */
    public static class FontMetricsInt {
        /**
         * The maximum distance above the baseline for the tallest glyph in
         * the font at a given text size.
         */
        public int   top;
        /**
         * The recommended distance above the baseline for singled spaced text.
         */
        public int   ascent;
        /**
         * The recommended distance below the baseline for singled spaced text.
         */
        public int   descent;
        /**
         * The maximum distance below the baseline for the lowest glyph in
         * the font at a given text size.
         */
        public int   bottom;
        /**
         * The recommended additional space to add between lines of text.
         */
        public int   leading;

        @Override public String toString() {
            return "FontMetricsInt: top=" + top + " ascent=" + ascent +
                    " descent=" + descent + " bottom=" + bottom +
                    " leading=" + leading;
        }
    }

他们的意义与值的计算方法分别如下:

  • ascent = ascent线的y坐标 - baseline线的y坐标;
  • descent = descent线的y坐标 - baseline线的y坐标;
  • top = top线的y坐标 - baseline线的y坐标;
  • bottom = bottom线的y坐标 - baseline线的y坐标;
    我们再来看个图:



    从这个图中,我们先说明两点,然后再回过头来看上面的公式:
    1、X轴,Y轴的正方向走向是X轴向右是正方向,Y轴向下是正方向,所以越往下Y坐标越大!
    2、大家千万不要将FontMetrics中的ascent,descent,top,bottom与现实中的ascent,descent,top,bottom所在线混淆!这几条线是真实存在的,而FontMetrics中的ascent,descent,top,bottom这个变量的值就是用来计算这几条线的位置的。下面我们将看到如何利用这几个变量来计算这几条线的位置。
    看完这个图,我们再重新说说这几个公式,我们拿一个来说吧,其它都是相同的道理。

ascent = ascent线的y坐标 - baseline线的y坐标;

FontMetrics的这几个变量的值都是以baseline为基准的,对于ascent来说,baseline线在ascent线之下,所以必然baseline的y值要大于ascent线的y值,所以ascent变量的值是负的。
同理,对于descent而言:

descent = descent线的y坐标 - baseline线的y坐标;

descent线在baseline线之下,所以必然descent线的y坐标要大于baseline线的y坐标,所以descent变量的值必然是正数。

下面,我们就来看看如何通过这些变量来得到对应线所在位置吧。
我们先列出来一个公式:

ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;
descent线Y坐标 = baseline线的y坐标 + fontMetric.descent;
top线Y坐标 = baseline线的y坐标 + fontMetric.top;
bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom;

获取FontMetrics对象是根据paint对象来获取的

        Paint paint = new Paint();
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();

从这里可以看到,通过paint.getFontMetrics()得到对应的FontMetrics对象。这里还有另外一个FontMetrics同样的类叫做FontMetricsInt,它的意义与FontMetrics完全相同,只是得到的值的类型不一样而已,FontMetricsInt中的四个成员变量的值都是Int类型,而FontMetrics得到的四个成员变量的值则都是float类型的。

实例:计算Text四线格位置

在这个例子中,我们先写一行字,然后画出这行字中的top线,ascent线,baseline线,descent线和bottom线。直接上代码

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;

        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);

        //计算各线位置
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float ascent = baseLineY + fontMetrics.ascent;
        float descent = baseLineY + fontMetrics.descent;
        float top = baseLineY + fontMetrics.top;
        float bottom = baseLineY + fontMetrics.bottom;
        Log.d("tag", "-----fontMetrics.ascent=" + fontMetrics.ascent + "----fontMetrics.descent=" + fontMetrics.descent);

        //画基线
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //画top
        paint.setColor(Color.BLUE);
        canvas.drawLine(baseLineX, top, 3000, top, paint);

        //画ascent
        paint.setColor(Color.GREEN);
        canvas.drawLine(baseLineX, ascent, 3000, ascent, paint);

        //画descent
        paint.setColor(Color.YELLOW);
        canvas.drawLine(baseLineX, descent, 3000, descent, paint);

        //画bottom
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, bottom, 3000, bottom, paint);
    }

这段代码中,总共分为三部分,写文字、计算各线所在位置、画出各条线;我们逐段来讲
先看写文字:

        int baseLineX = 0;
        int baseLineY = 200;

        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);
        canvas.drawText("Android \'s Blog", baseLineX, baseLineY, paint);

有关drawText的问题我们已经讲过,在这段代码中,我们需要注意的是两点:

  • 1、drawText中的参数y是基线的位置
  • 2、paint.setTextAlign(Paint.Align.LEFT);设置的相对位置为,指定的原点(0,200)在绘制矩形的左侧。换句话说,所绘制的文字所在矩形在(0,200)点的右侧

然后是计算各各线的y坐标位置:

//计算各线在位置
Paint.FontMetrics fm = paint.getFontMetrics();
float ascent = baseLineY + fm.ascent;
float descent = baseLineY + fm.descent;
float top = baseLineY + fm.top;
float bottom = baseLineY + fm.bottom;

首先,利用 paint.getFontMetrics()得到FontMetrics的实例,然后利用我们上面的公式即可得到各条线的y坐标。最后就是利用这些y坐标画出这些线了,很简单,就是drawLine的使用。

字符串所占高度

字符串所占高度很容易得到,直接用bottom线所在位置的Y坐标减去top线所在位置的Y坐标就是字符串所占的高度:
代码如下:

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float top = baseLineY + fontMetrics.top;
        float bottom = baseLineY + fontMetrics.bottom;

        //所占高度
        int height = (int) (bottom - top);
        Log.d("tag", "-----height" + height);

字符串所占宽度

// 宽度是非常容易得到的,直接利用下面的函数就可以得到
// int width = paint.measureText(String text);
Paint paint = new Paint();
//设置paint
paint.setTextSize(90); //以px为单位
//获取宽度
int width = (int)paint.measureText("Android 's Blog");

最小矩形

要获取最小矩形,也是通过系统函数来获取的,函数及意义如下:

/**
 * 获取指定字符串所对应的最小矩形,以(0,0)点所在位置为基线
 * @param text  要测量最小矩形的字符串
 * @param start 要测量起始字符在字符串中的索引
 * @param end   所要测量的字符的长度
 * @param bounds 接收测量结果
 */
public void getTextBounds(String text, int start, int end, Rect bounds);
        Paint paint = new Paint();
        String text = "Android \'s Blog";
        //设置paint
        paint.setTextSize(90); //以px为单位

        Rect minRect = new Rect();
        paint.getTextBounds(text, 0, text.length(), minRect);
        Log.e("tag", "----最小矩形" + minRect.toShortString());

在这段代码中,首先设置字体大小,然后利用paint.getTextBounds()得到最小矩形,最后,我将其打印出来
结果如下:

2020-06-06 12:47:59.659 14195-14195/com.as.customview E/tag: ----最小矩形[1,-68][584,19]

可以看到这个矩形的左上角位置为(1,-68),右下角的位置为(584,19);
大家可能会有疑问,为什么左上角的Y坐标是个负数?从代码中,我们也可以看到,我们并没有给getTextBounds()传递基线位置。那它就是以(0,0)为基线来得到这个最小矩形的!所以这个最小矩形的位置就是以(0,0)为基线的结果!
得到最小矩形的实际位置



在上面这个图中,我们将黑色矩形平行下移距离Y(黄色线依照的是基线的位置),那么平移后的左上角点的y坐标就是 y2 = y1 + Y;
同样的道理,由于paint.getTextBounds()得到最小矩形的基线是y = 0;那我们直接将这个矩形移动baseline的距离就可以得到这个矩形实际应当在的位置了。
所以矩形应当所在实际位置的坐标是:

Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
//最小矩形,实际top位置
int minTop = bounds.top + baselineY;
//最小矩形,实际bottom位置
int minBottom = bounds.bottom + baselineY;

下面我们就举个例子来看一下我们列举的这几个函数的使用方法

我们先看一下完整的代码,然后再细讲

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "Android \\'s Blog";
        int baseLineY = 200;
        int baseLineX = 0;

        //设置paint
        Paint paint = new Paint();
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);

        //画text所占的区域
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int top = baseLineY + fontMetricsInt.top;
        int bottom = baseLineY + fontMetricsInt.bottom;
        int width = (int) paint.measureText(text);
        Rect rect = new Rect(baseLineX, top, baseLineX + width, bottom);

        paint.setColor(Color.GREEN);
        canvas.drawRect(rect, paint);

        //画最小矩形
        Rect minRect = new Rect();
        paint.getTextBounds(text, 0, text.length(), minRect);
        minRect.top = baseLineY + minRect.top;
        minRect.bottom = baseLineY + minRect.bottom;
        paint.setColor(Color.RED);
        canvas.drawRect(minRect, paint);

        //写文字
        paint.setColor(Color.BLACK);
        canvas.drawText(text, baseLineX, baseLineY, paint);
    }

这段代码总共分为四部分:设置paint,画字符串所占据矩形,画最小矩形,画文字

1:设置paint

        String text = "Android \\'s Blog";
        int baseLineY = 200;
        int baseLineX = 0;

        //设置paint
        Paint paint = new Paint();
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);

2:画text所占的区域

        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int top = baseLineY + fontMetricsInt.top;
        int bottom = baseLineY + fontMetricsInt.bottom;
        int width = (int) paint.measureText(text);
        Rect rect = new Rect(baseLineX, top, baseLineX + width, bottom);
      
        paint.setColor(Color.GREEN);
        canvas.drawRect(rect, paint);

这里就是利用我们前面我们讲过的获取top线和bottom线的方法,获取宽度时就是利用paint.measureText(text);
但需要注意的是:矩形右下角的值并不一定是baselinex+width!它的具体取值是跟paint.setTextAlign(Paint.Align.LEFT)有关的,因为我们这里设置为Paint.Align.LEFT,所以是baselinex+width。如果设置为Paint.Align.CENTER,那么右下角的X坐标值为baselinex+width/2;再者如果设置为Paint.Align.RIGHT,那么右下角的X坐标就是baselineX;所占矩形的四个角的所有位置是与paint.setTextAlign()的设置紧密相关的,至于各个点的计算方法就不再细讲了,根据我们前面讲的paint.setTextAlign()的显示效果是非常容易想到的。

画最小区域矩形

Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
minRect.top = baseLineY + minRect.top;
minRect.bottom = baseLineY + minRect.bottom;
 
paint.setColor(Color.RED);
canvas.drawRect(minRect,paint);

这部分也就没什么难度了,首先根据paint.getTextBounds()得到基线为y=0的最小矩形的各点坐标,然后根据基线得到其实际的top和bottom坐标;然后将其画出来即可

给定左上顶点绘图

讲完上面的三部分,这篇文章所要讲的知识点基本就结束了,这部分其实就是应用的范畴了,因为我们会给定矩形左上角顶点(left,top),所以们先画出top线的位置,然后计算出baseline的位置,并画出来。最后根据baseline把文字写出来。

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "Android \'s Blog";
        int top = 200;
        int baseLineX = 0;

        //设置paint
        Paint paint = new Paint();
        paint.setTextSize(90); //以px为单位
        paint.setTextAlign(Paint.Align.LEFT);

        //画top线
        paint.setColor(Color.YELLOW);
        canvas.drawLine(baseLineX, top, 3000, top, paint);

        //计算出baseLine位置
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int baseLineY = top - fontMetricsInt.top;

        Log.d("tag", "-----fontMetricsInt.top=" + fontMetricsInt.top
                + "-----fontMetricsInt.bottom=" + fontMetricsInt.bottom
                + "-----fontMetricsInt.ascent=" + fontMetricsInt.ascent
                + "-----fontMetricsInt.descent=" + fontMetricsInt.descent
        );

        //画基线
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        canvas.drawText(text, baseLineX, baseLineY, paint);
    }

这段代码,比较简单,首先是我们给定top位置int top = 200;然后根据top线位置计算出baseline所在位置,并画出来:

      //计算出baseLine位置
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int baseLineY = top - fontMetricsInt.top;

        //画基线
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

给定中间线位置绘图


baseline = center + B = center + C - FontMetrics.bottom = center + (FontMetrics.bottom - FontMetrics.top)/2 - FontMetrics.bottom;
下面我们举个例子来说明下这个公式的用法

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "And \'s blog";
        int center = 200;
        int baseLineX = 0 ;

        //设置paint
        Paint paint = new Paint();
        paint.setTextSize(120); //以px为单位
        paint.setStrokeWidth(3);
        paint.setTextAlign(Paint.Align.LEFT);

        //画center线
        paint.setColor(Color.YELLOW);
        canvas.drawLine(baseLineX, center, 3000, center, paint);

        //计算出baseLine位置
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int baseLineY = center + (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom;

        //画基线
        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);

        //写文字
        paint.setColor(Color.GREEN);
        canvas.drawText(text, baseLineX, baseLineY, paint);
    }

这段代码也没什么难度,给定中间线的位置为200,然后计算出baseline的位置,然后把文字在baseline的基础上画出来。

好了,有关文字的绘图到这里就结束了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342