canvas教程

学习canvas.drawText

字号+ 作者:H5之家 来源:H5之家 2017-01-15 14:02 我要评论( )

本来这篇文章是要写写我在设计高级跑马灯程序的心得的,但是编写过程中花了近一天多的时间搞明白canvas.drawText中的第三个参数[float y]代表的真实含义。学习本文应该能帮助大家掌握FontMetrics类和Rect类成员变量值具体含义。 drawText引出问题 先来看看ap

本来这篇文章是要写写我在设计高级跑马灯程序的心得的,但是编写过程中花了近一天多的时间搞明白canvas.drawText中的第三个参数[float y]代表的真实含义。学习本文应该能帮助大家掌握FontMetrics类和Rect类成员变量值具体含义。

drawText引出问题

先来看看api中是如何定义drawText的参数。

/** * Draw the text, with origin at (x,y), using the specified paint. The * origin paint. * * @param text The text to be drawn * @param x The x-coordinate being drawn * @param y The y-coordinate being drawn * @param paint The paint used (e.g. color, size, style) */ public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface); }

简单解释下各参数:
@param text:要显示的文本内容,这个不难理解。
@param x:文本相对屏幕原点x方向距离,没有更深的含义,也比较好理解
@param y:文本的baseline相对屏幕原点y方向距离。好,问题来了,baseline是个什么鬼东东
@param paint:画笔

baseline的来龙去脉

先看看baseline在文字区域的位置。通过一个实例来分析,这里只贴主要的code。

@Override protected void onDraw(Canvas canvas) { //super.onDraw(canvas); mRect = new Rect(); mPaint = new Paint(); mPaint.setTextSize(64); mPaint.setColor(Color.RED); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); mPaint.getTextBounds(textStr, 0, textStr.length(), mRect); int w = mRect.width(); int h = mRect.height(); mRect = new Rect(mRectLeft, mRectTop, mRectLeft+w, mRectTop+(-fontMetrics.top)+fontMetrics.bottom); canvas.drawRect(mRect, mPaint); mBaseLine = (mRect.bottom+mRect.top)/2 - (fontMetrics.bottom+fontMetrics.top)/2; mBaseLine = -fontMetricsmPaint.setColor(Color.WHITE); canvas.drawText(textStr, mRectLeft, mBaseLine, mPaint); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(3); /*将mBaseLine所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine, mRectLeft+w, mBaseLine, mPaint); }

效果图:

这里写图片描述

分析

从上图可以看出来,baseline并不是文字区域的底部,但是这根线的位置相信大家都熟悉,除非你没有学过英语。

FontMetrics

FontMetrics是Paint静态内部类,主要定义了Paint绘制文本时的关键坐标。API中这么描述:

Class returned by getFontMetrics().

主要意思:根据设定的fontsize来获得字体的各种变量值。通过getFontMetrics()方法来获取。
FontMetrics类含有5个成员变量:

{ /** * The maximum distance above the baseline for the tallest glyph in * the font at a given text size. */ public float top; /** * The recommended distance above the baseline for singled spaced text. */ public float ascent; /** * The recommended distance below the baseline for singled spaced text. */ public float descent; /** * The maximum distance below the baseline for the lowest glyph in * the font at a given text size. */ public float bottom; /** * The recommended additional space to add between lines of text. */ public float leading; }

很明显所有的值都是基于baseline来算的。这里我主要关注top这个值的定义。
top:api的注释翻译过来意思是字体可绘制区域最高位置与baseline的距离。但是它是个负数,所以-top就是我们的baseline坐标值。
ascent:字体下单个字符最高位置与baseline的距离
descent:字体下单个字符最低位置与baseline的距离,与ascent镜像对应
bottom:字体可绘制区域最低位置与baseline的距离。
leading:字面翻译是文本线额外的空间。一般都为0,不知道有何用处。

Rect

Rect类表示的一块矩形区域。Paint类中getTextBounds()方法可以获取对应font size下文本所占用矩形区域。记住这个矩形区域的坐标值也是相对baseline来计算的。
Rect类成员变量有4个,分别是left、top、right、bottom。由于文本的rect区域是相对baseline来计算的,因此真实的top跟bottom都要加上baseline的值。

借助一个实例来理解FontMetrics和Rect

主要源码:

@Override protected void onDraw(Canvas canvas) { //super.onDraw(canvas); mRect = new Rect(); mPaint = new Paint(); mPaint.getTextBounds(textStr, 0, 1, mRect); mPaint.setTextSize(textSize); mPaint.setColor(0xffF4A460); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); mPaint.getTextBounds(textStr, 0, textStr.length(), mRect); int w = mRect.width(); int h = mRect.height(); /*给fontMetrics区域填充0xffF4A460色*/ mRect = new Rect(mRectLeft, mRectTop, mRectLeft+w, mRectTop+(-fontMetrics.top)+fontMetrics.bottom); canvas.drawRect(mRect, mPaint); /*计算baseline,其中mRectTop是控件顶部到父view的距离*/ mBaseLine = -fontMetrics.top + mRectTop; /*其中y == mBaseLine的值*/ mPaint.setColor(Color.WHITE); canvas.drawText(textStr, mRectLeft, mBaseLine, mPaint); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(4); /*蓝色线:将mBaseLine所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine, mRectLeft+w, mBaseLine, mPaint); mPaint.setColor(Color.GREEN); /*绿色线:将文字区域的bottom所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.bottom, mRectLeft+2*w , mBaseLine+fontMetrics.bottom, mPaint); mPaint.setColor(Color.RED); /*红色线:将文字区域的top所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.top, mRectLeft+2*w , mBaseLine+fontMetrics.top, mPaint); mPaint.setColor(Color.GRAY); /*灰色线:将文字区域的ascent所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.ascent, mRectLeft+w+50 , mBaseLine+fontMetrics.ascent, mPaint); mPaint.setColor(Color.WHITE); /*白色线:将文字区域的descent所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.descent, mRectLeft+w+50 , mBaseLine+fontMetrics.descent, mPaint); mPaint.setColor(Color.YELLOW); /*黄色线:将文字区域的leading所在的位置画出来*/ canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.leading, mRectLeft+w/2 , mBaseLine+fontMetrics.leading, mPaint); /*将“测”字的rect用矩形绘出来*/ mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.getTextBounds(textStr, 0, 1, mRect); mRect.top+=mBaseLine; mRect.bottom+=mBaseLine; canvas.drawRect(mRect, mPaint); /*将“测试:12hg”字的rect用矩形绘出来*/ mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.getTextBounds(textStr, 0, 7, mRect); mRect.top+=mBaseLine; mRect.bottom+=mBaseLine; canvas.drawRect(mRect, mPaint); }

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • canvas学习之路(一)基础绘图功能解析

    canvas学习之路(一)基础绘图功能解析

    2017-01-15 14:03

  • 如何学习web前端开发 有没有什么技巧

    如何学习web前端开发 有没有什么技巧

    2017-01-15 13:02

  • canvas基础学习(二),canvas基础学习

    canvas基础学习(二),canvas基础学习

    2017-01-14 08:00

  • canvas学习(一)

    canvas学习(一)

    2017-01-13 18:04

网友点评