自己定义控件之画图篇( 五):drawText()具体解释

前言:但行好事。莫问前程。仅仅需努力每一天。

相关文章:

《Android自己定义控件三部曲文章索引》:  http://blog.csdn.net/harvic880925/article/details/50995268

long long ago,有讲过有关Canvas画图的系列知识。当时着重在基本画图要领和canvas的保存与回退上,对drawText没有细讲,但DrawText这个函数,确是相当复杂。这里开一篇又一次解说一下。


一、概述

1、四线格与基线

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


那么问题来了。在canvas在利用drawText绘制文字时,也是有规则的,这个规则就是基线!


我们先来看一下什么是基线:


可见基线就是四线格中的第三条线!


也就是说。仅仅要基线的位置定了。那文字的位置必定是定了的!


2、canvas.drawText()

(1)、canvas.drawText()与基线

以下我们来又一次看看canvas.drawText()这个函数。有关drawText的全部drawText()函数的基本使用方法。在文章《android Graphics(二):路径及文字》中已经讲过。这里就不再一一解说,仅仅拿出一个来解说下drawText与基线的关系:

/**
* text:要绘制的文字
* x:绘制原点x坐标
* y:绘制原点y坐标
* paint:用来做画的画笔
*/
public void drawText(String text, float x, float y, Paint paint)
上面这个构造函数是最经常使用的drawText方法,传进去一个String对象就能画出相应的文字。
但这里有两个參数须要非常注意,表示原点坐标的x和y.非常多同学可能会觉得。这里传进去的原点參数(x,y)是所在绘制文字所在矩形的左上角的点。但实际上并非!比方,我们上面假设要画"harvic's blog"这几个字。这个原点坐标应当是下图中绿色小点的位置

在(x,y)中最让人捉急的是y坐标,一般而言,(x,y)所代表的位置是所画图形相应的矩形的左上角点。

但在drawText中是非常例外的,y所代表的是基线的位置!

(2)实例

以下我们就举个样例来看一下drawText中。原点坐标(x,y)的位置。
1、首先,新建一个projectblogDrawText,然后自己定义一个View:MyView

public class MyView extends View{

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}
2、重写onDraw函数:
我们重写MyView的onDraw函数。自己定义一个基线,然后利用drawText画出来:
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

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

    //写文字
    paint.setColor(Color.GREEN);
    paint.setTextSize(120); //以px为单位
    canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
}
在这里,先定义drawText原点的位置:(0,200)
首先,我们把(0,200)所在的这条横线画出来。所以我先画了一条线从点坐标为(0,200)到点坐标为(3000,200)的一条直线
然后利用canvas.drawText以(0,200)为原点画出文字
3、在main.xml中加入使用代码:
<?

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" > <com.example.blogDrawText.MyView android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>

效果图例如以下:

结论:

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

3、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()来设置相对位置来看看结果。


(1)、setTextAlign(Paint.Align.LEFT)
在原来代码上加上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(120); //以px为单位
    paint.setTextAlign(Paint.Align.LEFT);
    canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
}
结果例如以下:

可见,原点(x,y)在矩形的左側,即矩形从(x,y)的点開始绘制
(2)、setTextAlign(Paint.Align.CENTER)
相同的代码,把相对位置设置为: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(120); //以px为单位
    paint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
}
结果为:

所以原点(x,y)就在所要绘制文字所在矩形区域的正中间。换句话说,系统会依据(x,y)的位置和文字所在矩形大小,会计算出当前開始绘制的点。以使原点(x,y)正好在所要绘制的矩形的正中间。
(3)、setTextAlign(Paint.Align.RIGHT)
将相对位置设置为: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(120); //以px为单位
    paint.setTextAlign(Paint.Align.RIGHT);
    canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
}
结果为:

所以原点(x,y)应当在所要绘制矩形的右側。在上面的代码中,也就是说正个矩形都在(0,200)的左側,所以我们看到的是什么都没有。
(4)、注意
以下,我们再看一个样例:
我们仅仅写一个大写字母A。然后将其相对位置设置为paint.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(120); //以px为单位
    paint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText("A", baseLineX, baseLineY, paint);
}
结果例如以下:

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

源代码在文章底部给出

二、drawText的四线格与FontMetrics

1、Text的画图四线格

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


除了基线以外,如上图所看到的。另外还有四条线。各自是ascent,descent,top,bottom,他们的意义各自是:

  • ascent: 系统建议的,绘制单个字符时,字符应当的最高高度所在线
  • descent:系统建议的,绘制单个字符时。字符应当的最低高度所在线
  • top: 可绘制的最高高度所在线
  • bottom: 可绘制的最低高度所在线
单从这几个定义。大家可能还是搞不清这几值究竟是什么意义。

我们来看一下电视的显示。用过视频处理工具的同学(比方premiere,AE,绘声绘影等),应该都会知道,在制作视频时,视频显示位置都会有一个安全区域框,例如以下图所看到的:


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


这个安全框是用来干嘛的?这个安全框就是系统推荐给我们的显示区域,尽管说我们能够讲电视屏幕是每一个区域都是能够显示图像的,但由于制式的不同。每一个国家的屏幕大小并不一定我们这里的屏幕大小一致,当遇到不一致时。就会裁剪。但系统给我们推荐的显示区域是不管哪种制式都是能够完整显示出来的,所以我们在制作视频时,尽量要把要显示的图像放在所推荐的显示区域内。
相同,在这里,我们在绘制文字时,ascent是推荐的绘制文字的最高高度,就表示在绘制文字时。尽力要在这个最高高度以下绘制文字。descent是推荐的绘制文字的最底高度线,相同表示是在绘制文字时尽量在这个descent线以上来绘制文字。而top线则指该文字能够绘制的最高高度线,bottom则是表示该文字能够绘制的最低高度线。ascent,descent是系统建议上的绘制高度,而top,bottom则是物理上屏幕最高。最低能够画的高度值。

他们的区别与我们上面说的视频处理的安全框和屏幕的道理是一样的。

2、FontMetrics

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

FontMetrics::ascent;
FontMetrics::descent;
FontMetrics::top;
FontMetrics::bottom;
他们的意义与值的计算方法分别例如以下:
  • 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变量的值必定是正数。
(2)、得到Text四线格的各线位置
以下。我们就来看看怎样通过这些变量来得到相应线所在位置吧。
我们先列出来一个公式:
ascent线Y坐标 = baseline线Y坐标 + fontMetric.ascent;
推算步骤例如以下:
由于ascent线的Y坐标等于baseline线的Y坐标减去从baseline线到ascent线的这段距离。


也就是:(|fontMetric.ascent|表示取绝对值)
ascent线Y坐标 = baseline线Y坐标 - |fontMetric.ascent|;
又由于fontMetric.ascent是负值。所以:
ascent线Y坐标 = baseline线Y坐标 - |fontMetric.ascent|;
ascent线Y坐标 = baseline线Y坐标 - ( -fontMetric.ascent);
ascent线Y坐标 = baseline线Y坐标 + fontMetric.ascent;
这就是整个推算过程,没什么难度,同理能够得到:

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

(3)、获取FontMetrics对象
获取FontMetrics对象是依据paint对象来获取的:

Paint paint = new Paint();
Paint.FontMetrics fm = paint.getFontMetrics();
Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();
从这里能够看到,通过paint.getFontMetrics()得到相应的FontMetrics对象。这里还有另外一个FontMetrics相同的类叫做FontMetricsInt。它的意义与FontMetrics全然相同,仅仅是得到的值的类型不一样而已。FontMetricsInt中的四个成员变量的值都是Int类型。而FontMetrics得到的四个成员变量的值则都是float类型的。
(4)、实例:计算Text四线格位置
以下,我们就举个样例来看一下怎样计算Text画图中各条线的位置的。


先来看一下效果图:


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

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

    Paint paint = new Paint();
    //写文字
    paint.setColor(Color.GREEN);
    paint.setTextSize(120); //以px为单位
    paint.setTextAlign(Paint.Align.LEFT);
    canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);

    //计算各线在位置
    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.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 baseLineY = 200;
int baseLineX = 0 ;

Paint paint = new Paint();

//写文字
paint.setColor(Color.GREEN);
paint.setTextSize(120); //以px为单位
paint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("harvic\'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的使用,难度不大,就不再细讲。


源代码在文章底部给出

三、所绘文字宽度、高度和最小矩形获取

这部分,我们将解说怎样获取所绘制字符串所占区域的高度、宽度和仅包裹字符串的最小矩形。我们来看张图来讲述下他们的意义:


在这张图中。文字底部的绿色框就是所绘制字符串所占领的大小。

我们要求的宽度和高度也就是这个绿色框的宽度和高度。
从图中也能够看到,红色框部分,它的宽和高紧紧包围着字符串,所以红色框就是我们要求的最小矩形。即能包裹字符串的最小矩形。


1、字符串所占高度和宽度

(1)、高度

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

Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int top = baseLineY + fm.top;
int bottom = baseLineY + fm.bottom;
//所占高度
int height = bottom - top;

(2)、宽度

宽度是非常easy得到的。直接利用以下的函数就能够得到
int width = paint.measureText(String text);
使用示比例如以下:
Paint paint = new Paint();

//设置paint
paint.setTextSize(120); //以px为单位
//获取宽度
int width = (int)paint.measureText("harvic\'s blog");

(3)、最小矩形

1、概述
要获取最小矩形,也是通过系统函数来获取的,函数及意义例如以下:
/**
 * 获取指定字符串所相应的最小矩形,以(0,0)点所在位置为基线
 * @param text  要測量最小矩形的字符串
 * @param start 要測量起始字符在字符串中的索引
 * @param end   所要測量的字符的长度
 * @param bounds 接收測量结果
 */
public void getTextBounds(String text, int start, int end, Rect bounds);
我们简单展示下使用代码及结果:
String text = "harvic\'s blog";
Paint paint = new Paint();
//设置paint
paint.setTextSize(120); //以px为单位

Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
Log.e("qijian",minRect.toShortString());
在这段代码中,首先设置字体大小。然后利用paint.getTextBounds()得到最小矩形,最后,我将其打印出来
结果例如以下:

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


2、得到最小矩形的实际位置
我们先来看一个原理:


在上面这个图中,我们将黑色矩形平行下移距离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;
3、实例
以下我们就举个样例来看一下我们列举的这几个函数的使用方法
效果图与这一节开篇时的效果图是一样的。例如以下:

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

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

String text = "harvic\'s blog";
int baseLineY = 200;
int baseLineX = 0 ;

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

//画text所占的区域
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int top = baseLineY + fm.top;
int bottom = baseLineY + fm.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,画字符串所占领矩形。画最小矩形。画文字
第一部分:设置paint
String text = "harvic\'s blog";
int baseLineY = 200;
int baseLineX = 0 ;

//设置paint
Paint paint = new Paint();
paint.setTextSize(120); //以px为单位
paint.setTextAlign(Paint.Align.LEFT);
设置paint这部分。主要是设置字体的大小,由于我们在字体所占的区域大小跟字体的大小是有直接关系的,假设不设置,那么在获取所占区域大小时,将利用系统默认的大小来測量了,当然是不行的。
第二部分:画text所占的区域
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int top = baseLineY + fm.top;
int bottom = baseLineY + fm.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);
然后利用求得到top,bottom,width来得到相应的矩形:Rect(baseLineX,top,baseLineX+width,bottom),这里要注意的是我们利用paint.measureText(text)得到的仅仅是宽度。矩形右下角的x坐标值为baselinex+width;
但须要注意的是:矩形右下角的值并不一定是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()的显示效果是非常easy想到的。


第三部分:画最小区域矩形

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坐标;然后将其画出来就可以
第四部分:画文字
这部分没什么难度。就不再讲了。


源代码在文章底部给出

四、定点写字

讲完上面的三部分,这篇文章所要讲的知识点基本就结束了。这部分事实上就是应用的范畴了。在这部分中。我们将讲述,当我们设定一个点,怎样到得基线位置。进而画出字符串。

1、给定左上顶点画图

这部分,我们假定给出所要绘制矩形的左上角顶点坐标,然后画出这个文字。
先来看个图片:


在这个图中,我们给定左上角的位置,即(left,top);我们知道要画文字。drawText()中传进去的Y坐标是基线的位置,所以我们就必须依据top的位置计算出baseline的位置。


我们来看一个公式:
FontMetrics.top = top - baseline;
所以baseline = top - FontMetrics.top;
由于FontMetrics.top是能够得到的,又由于我们的top坐标是给定的。所以通过这个公式就能得到baseline的位置了。
以下举个样例来说明一下依据矩形左上项点绘制文字的过程:
先看下效果图:


在这个效果图中。由于我们会给定矩形左上角顶点(left,top),所以们先画出top线的位置,然后计算出baseline的位置。并画出来。最后依据baseline把文字写出来。
代码例如以下:

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

	String text = "harvic\'s blog";
	int top = 200;
	int baseLineX = 0 ;
	
	//设置paint
	Paint paint = new Paint();
	paint.setTextSize(120); //以px为单位
	paint.setTextAlign(Paint.Align.LEFT);
	
	//画top线
	paint.setColor(Color.YELLOW);
	canvas.drawLine(baseLineX, top, 3000, top, paint);
	
	//计算出baseLine位置
	Paint.FontMetricsInt fm = paint.getFontMetricsInt();
	int baseLineY = top - fm.top;
	
	//画基线
	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 fm = paint.getFontMetricsInt();
int baseLineY = top - fm.top;

//画基线
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);
最后就是写出文字了,没什么难度就不讲了。
源代码在文章底部给出

2、给定中间线位置画图

先来看一张图:

在这个图中,总共同拥有四条线:top线,bottom线。baseline和center线。
图中center线正是在top线和bottom线的正中间。
为了方便推导公式。我另外标了三个距离A,B,C;
非常显然,距离A和距离C是相等的,都等于文字所在矩形高度以的一半,即:
A = C = (bottom - top)/2;
又由于bottom = baseline + FontMetrics.bottom;
top = baseline+FontMetrics.top;
所以。将它们两个代入上面的公式。就可得到:
A = C = (FontMetrics.bottom - FontMetrics.top)/2;
而距离B,则表示Center线到baseline的距离。
非常显然距离B = C - (bottom - baseline);
又由于
FontMetrics.bottom = bottom-baseline;
C = A;
所以,B = A - FontMetrics.bottom;
所以baseline = center + B = center + A - FontMetrics.bottom = center + (FontMetrics.bottom - FontMetrics.top)/2 - FontMetrics.bottom;

依据上面的推导过程,我们终于可知,当给定中间线center位置以后,baseline的位置为:

baseline = center + (FontMetrics.bottom - FontMetrics.top)/2 - FontMetrics.bottom;
以下我们举个样例来说明下这个公式的使用方法。


效果图例如以下:


代码例如以下:

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    
    String text = "harvic\'s blog";
    int center = 200;
    int baseLineX = 0 ;

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

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

    //计算出baseLine位置
    Paint.FontMetricsInt fm = paint.getFontMetricsInt();
    int baseLineY = center + (fm.bottom - fm.top)/2 - fm.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的基础上画出来。
源代码在文章底部给出
最后一部分给定定点计算baseline位置的东东。大家不必刻意去记,没什么用,当大家须要时,自己依据FontMetrics,最小矩形,及各条线的意义,自己来推导就能够了。

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


假设本文有帮到你。记得加关注哦

源代码下载地址:http://download.csdn.net/detail/harvic880925/9383971

请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/50423762 谢谢


posted @ 2017-08-15 14:32  jzdwajue  阅读(700)  评论(0编辑  收藏  举报