Android中静态和动态文字的绘制和测量
Android中自定义视图的时候存在两种情况,静态文字和动态文字。
顾名思义,静态文字就是显示内容是固定的,不会产生变化的文字,而动态文字则是内容会不断产生变化的文字信息。
在说明为什么要在绘制文字的时候区分静态文字和动态文字之前,我们需要首先讲一讲,静态文字的测量和绘制方式,静态文字的绘制我们需要基于静态文字的边框来决定。
在我们调用drawText时,系统api会根据paint.textAlign,基准点的基础上,基于基线进行绘制,文字的基线往往在文字的底部,所以如果将基准点设置为视图的中心,那么就难免会造成文字整体绘制位置过于偏上的问题。这个时候就需要基于文字的测量边框来适当进行基准点的偏移了。
请注意,这里rect.top和rect.bottom都是相对于基线的偏移量(可能为负值,表示文字顶部或者底部在基线的上面),而不是我们文字在屏幕中的相对坐标原点的距离,因为调用getTextBounds的时候,我们还没有绘制文字呢?那系统又怎么知道我们打算到哪里去绘制文字呢?所以解决我们上述所说的文字整体向上偏移的问题,我们只需要将基准点向下移动,文字中心线和baseline的差值即可。
基本的操作流程如下:
val s = "abp"//待绘制的文字
val rect: Rect = Rect()//用于存储边框信息的容器
paint.getTextBounds(s, 0, s.length, rect)//获取文字的边框并存储到容器里
paint.textAlign = Paint.Align.CENTER//文字基于指定坐标居中显示
canvas.drawText(s, 0, s.length, centerX, centerY - (rect.top + rect.bottom) / 2, paint)//基于文字定义的边框进行文字绘制的偏移
好了,说完了静态文字的绘制问题,我们来讲讲为什么要对静态问题和动态文字进行分开处理。
之所以要对于这两种情况需要区分处理,是因为像英语这样的语言,其不像汉字一样,大多数是方块字,都基本能够填充满整个格子。像英语这样的语言,为了其显示内容的美观,其内容文字多多少少会产生各种各样的偏移,从而让其文字的主要部分居中对齐显示,比如说,b和p两个字母中的“圆圈O”部分对齐我们才会觉得显示是十分自然和好看的。
也正因此,当一串文字一直发生变动时,对于同一个字母,如果还是按照静态文字那一套,就会发生字母一直在上下晃动的问题。那么如何解决这个问题呢?我们需要采取一个折衷的方式来解决对应的问题了。在分析文字的时候,官方给出了对应的API:paint.getFontMetrics(fontMetrics)
来获取字体的相关配置,通过API我们可以获取到文字的主体部分的top和bottom,为了区分,官方将其分别命名为ascent,descent。我们只需要按照之前的方式根据字体的ascent和decent来对绘制基准点进行偏移即可完成对应的文字绘制。
基本的绘制流程如下:
val fontMetrics = Paint.FontMetrics()
paint.getFontMetrics(fontMetrics)
val newBaseLine = (fontMetrics.descent + fontMetrics.ascent) / 2
canvas.drawText(s, 0, s.length, centerX, centerY - newBaseLine, paint)
好了,自定义视图的文字绘制基本内容差不多就是这么多了,这部分内容还有另外一个,就是如何自定义视图实现文字环绕图片的效果。