理解FontMetrics和canvas.drawText绘制坐标点

理解FontMetrics和canvas.drawText绘制坐标点

Android小彩虹2021-07-17 23:14:37100A+A-

在ui开发开发中,label文本标签是最长用到的。android中提供了TextView帮我们用来展示文本文字。而android的Canvas也提供了drawText用于帮助我们在自定义view的时候绘制展示文本。

先简单看一下这段代码

private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

init {
    paint.textSize = 150F
    paint.style = Paint.Style.FILL_AND_STROKE
    paint.color = Color.parseColor("#FFFFFF")
}

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    canvas?.drawColor(Color.parseColor("#80F14400"))
    val textLabel = "Hello World, Hello Python"
    canvas?.drawText(textLabel, 0F, 0F, paint)
}

上面这段代码,是一个最简单的drawText使用。按照我们对android坐标系的理解,貌似没什么问题,应该是在view的左上角绘制文本,文本完整展示。 在这里插入图片描述 从真实的展示上效果来看,和我们想要的效果完全不一致,为什么会出现这种情况呢?还是看一下drawText的方法定义吧。 在这里插入图片描述 从方法的注释中可以得知drawTextxy分别是用来定义文字绘制的起始点,而这个起始点的y坐标是基于baseline(基线)。想要理解baseline的概念,就要理解文字的测量规则,canvas文字测量规则是使用FontMetrics方法中定义的。而FontMetrics是从Paint.getFontMetrics()获取。

在看FontMetrics定义之前,先看一下这张图,这张图是从别人博客copy过来的(对于图片中的leading值,图中理解不是很正确,暂时忽略)

leading 指的是行的额外间距,即对于上下相邻的两行,上行的 bottom 线和下行的 top 线的距离

在这里插入图片描述

FontMetics类主要是定义了文字的测量属性。

public static class FontMetrics {
    /** * 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;
}

从上面的FontMetrics定义中以及drawText中可以发现,都是使用baseline作为一个基准线来确定距离。

可以看出来baseline的确认很重要,那么接下来看一下baseline怎么计算。 在这里插入图片描述 从图中可以看出来,baseline的大小y值等于fontMetrics.bottom + fontMetrics.top -fontMetrics.descent 。那么,可以打印一下FontMetrics的各个属性的值,看一下输出。

val fontMetrics = paint.fontMetrics
Log.e("info", "fontMetrics-->top: " + fontMetrics.top)
Log.e("info", "fontMetrics-->leading: " + fontMetrics.leading)
Log.e("info", "fontMetrics-->ascent: " + fontMetrics.ascent)
Log.e("info", "fontMetrics-->descent: " + fontMetrics.descent)
Log.e("info", "fontMetrics-->bottom: " + fontMetrics.bottom)

E/info: fontMetrics-->top: -157.2 E/info: fontMetrics-->leading: 0.0 E/info: fontMetrics-->ascent: -139.2 E/info: fontMetrics-->descent: 36.600002 E/info: fontMetrics-->bottom: 40.65

将打印的结果对照图,会发现,起始数据基于baseline,在baseline上方的为负数、下方的为正数。

知道了怎么每个值的意义和baseline的计算方式之后,我们就可以根据baseline作为绘制出来每个属性的辅助线和文字

val fontMetrics = paint.fontMetrics
val baseline = fontMetrics.bottom + kotlin.math.abs(fontMetrics.top) - fontMetrics.descent
canvas?.save()
//将坐标零点y值移动到baseline
canvas?.translate(
    0F,
    baseline
)
paint.color = Color.BLUE
val textLabel = "Hello,Python"
canvas?.drawText(textLabel, 0F, 0F, paint)
paint.style = Paint.Style.STROKE
//绘制top
paint.color = Color.BLUE
canvas?.drawLine(0F, fontMetrics.top, width.toFloat(), fontMetrics.top, paint)
paint.color = Color.YELLOW
//绘制ascent
canvas?.drawLine(0F, fontMetrics.ascent, width.toFloat(), fontMetrics.ascent, paint)
paint.color = Color.GRAY
//绘制descent
canvas?.drawLine(0F, fontMetrics.descent, width.toFloat(), fontMetrics.descent, paint)
paint.color = Color.parseColor("#F15500")
//绘制bottom
canvas?.drawLine(0F, fontMetrics.bottom, width.toFloat(), fontMetrics.bottom, paint)
//绘制baseline
paint.color = Color.parseColor("#8080FF")
paint.pathEffect = DashPathEffect(floatArrayOf(10F, 10F), 0F)
canvas?.drawLine(0F, 0F, width.toFloat(), 0F, paint)
canvas?.restore()

在这里插入图片描述

如果想要系统的了解,欢迎订阅我的TextView专题讲解,让你彻底读懂textView绘制原理,从源码角度理解谷歌设计思路。

欢迎点我查看-带你彻底搞懂Textview绘制原理

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1

联系我们