Android Canvas绘制文字横纵向对齐

目录
  • 1. 横向对齐(Align属性)
  • 2. TextBound
  • 3. 纵向对齐与绘制线
  • 4. 总结

1. 横向对齐(Align属性)

Align属性决定了使用该画笔时,相较于绘制点的水平对称方式,分别是LEFT、CENTER、RIGHT,对应的情况:

如最上方的文字及其框线所示,文字具有三个备选的初始绘制基点,Align属性将会指定这三个绿色的哪一个基点最终和绘制目标基点进行重合对齐。

红色的点就是我们在drawText()中填入的xy坐标参数,我们暂且将其称为目标基点(x,y)被确定之后,文字绘制的基线baseline就可以确定了。而Align属性,正是决定了使用文字的左、中、右,具体哪一个点作为参照点和绘制的基点进行重合,例如我们设置align = Align.LEFT,那么就是文字的左边一个初始基点与目标基点(x,y)进行对齐,绘制的结果就是所有文字都在基点的右边

注意:以上的图片只是理想情况,实际绘制时,如果不作处理,那么你会发现在LEFT、RIGHT模式中,框线和目标基点(x,y)之间还有一小段距离。

2. TextBound

该属性本质上是一个矩形(Rect),如果我们将该矩形绘制在屏幕上,那么它的位置非常奇怪,它会出现在左上角的位置上,如下图左上角黑色框线:

实际上,我们不应该不经过处理直接将这个矩形绘制出来,因为它所对应的实际的量仅仅代表的是我们当前绘制字符的Bound,即边界,我们利用bound.right - bound.left就可以得到使用当前Paint绘制当前字符最终得到的宽度,同理可以得到绘制字符的高度。而它实际的数值标识的意义应该是在Align.LEFT模式下,左右、上下框线距离绘制基点的偏移量。例如如下视图,对应的数据分别是:

如果我们使用如下代码将Text绘制在Canvas的中心,同时将Bounds也按照一定的偏移绘制出来,让它紧紧地贴着文字:

// 绘制内部文字,centerPoint是一个数组,存储了视图中心点的坐标
canvas?.drawText(mText, centerPoint[0], centerPoint[1], mTextPaint.apply {
    textAlign = Paint.Align.LEFT
})

// 绘制框线
canvas?.drawRect(
  centerPoint[0] + mTextBound.left,
  mTextBound.top.toFloat() + centerPoint[1],
  mTextBound.right.toFloat() - mTextBound.left.toFloat() + centerPoint[0],
  mTextBound.bottom.toFloat() + centerPoint[1],
  mTextBoardPaint.apply {
    strokeWidth = 8f
  }
)

其中黑色的点是整个视图的中心,细心的小伙伴可能发现了,黑点并不是文字的最左下方,而是偏靠上了一点点,我们把这条线延展出来,那么就可以得到该文字的绘制基线:Baseline

为什么要设置这样一个Baseline呢?

其实不难发现,基线以上,几乎包括了95%的文字内容,而基线以下,只有p、q、Q的尾部。主要部分完全都被包含在了基线之上。基线其实是西文字体设计与排版的概念,源自西文字母的主体底部对齐的位置,如果直接按照bounds的底部进行绘制文字,显然这些p、q、Q的尾部是无法处理的。但是如果只有字符「abcd」的情况下,你会发现文字的边框完全贴着a的底部,因为在这种特殊的情况下,基线和bound的底部完全重合了。

但基线对于中文来说并没有多大的意义,但是它却一定程度上影响到了我们绘制时所期望的定位方式,我们肯定是希望文字一定是严格按照文字的左下角、中心下角、右下角来绘制的,我们不希望文字底部和这个基线之间还有一小段距离。这个问题在一些需要做到竖直居中的场景中尤为尖锐,譬如我们希望在圆形中嵌入一个字符,标识某种信息,如果我们直接在视图中心drawText,绘制出的文字却不在视图的中心:

原因很简单,文字的纵向中心和图像的纵向中心并不重合。

3. 纵向对齐与绘制线

  • leading : 上一行文字的descent到当前行文字的ascent称为行距
  • Top最高字符Baseline的值,以Baseline为基准,向下为正(通常Top为负值)
  • Asecnt:Baseline之上至字符最高处的距离,以Baseline为基准,向下为正(通常为负值)
  • Baseline:文字绘制的基准,该属性并不在fontMetrics中显示地给出,通常设置Paint的Align的时候,我们所设置的点的水平延长线就是基线
  • Descent :Baseline之下至字符最低处的距离,以Baseline为基准,向下为正(通常为正值)
  • Bottom最下字符Baseline的值,以Baseline为基准,通常为正值

在Android中,我们可以使用:Paint.getFontMetrics()获取以上的绝大部分数值(除了Baseline)。

其中,Descent和Ascent中容纳了整个文字的内容,除去p、q的尾部,其余的主要内容则位于基线和Ascent之间,在一些特殊的文字系统中,可能含有「Ö」这一类的字符:

这样就会将文字的bound撑开到Ascent的位置,此时的bound中线和Ascent/Descent几乎完全重合了,对于上面提到的居中的问题,我们也不难得到一个解决方案,将文字绘制的起点向下偏移一小段距离即可完成居中,而这偏移的一小段距离应该是文字bound居中线y坐标和绘制起点y坐标之间的差值,如下图X标注:

代码如下:

  canvas?.drawText(mText, centerPoint[0], centerPoint[1] + mTextBound.bottom, mTextPaint.apply {
    textAlign = Paint.Align.CENTER
  })

只需要将绘制基点向下移动:基线到文字底部的距离,即bound.bottom即可:

4. 总结

绘制线(Metrics)是由Paint和字体共同决定的,当一个Paint和字体确定了,那么上述的绘制线就已经确定了,并不会因为文字内容的变化而被修改;而textBound则是文字绘制的边界,我们使用Paint.getTextBounds()可以去测量特定内容的边界值,其值根据文本的内容的不同而有所不同。在绘制内容中,如果含有当前字符集中的最“高”的字符时,bound的bottom、top与绘制线的Ascent、Descent之间分别会重合。

因此,Ascent和Descent之间是当前字符集中最高文字的顶和底,它不一定出现在你的内容当中;而bounds的top和bottom对应的中心,则是你实际绘制的内容的纵向中心。

到此这篇关于Android Canvas绘制文字横纵向对齐的文章就介绍到这了,更多相关Android Canvas绘制 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 使用Canvas在图片上绘制文字的方法

    [Android]Android中 Paint 字体.粗细等属性的一些设置 在Android SDK中使用Typeface类来定义字体,可以通过常用字体类型名称进行设置,如设置默认黑体: Paint mp = new paint(); mp.setTypeface(Typeface.DEFAULT_BOLD) 常用的字体类型名称还有: * Typeface.DEFAULT //常规字体类型 * Typeface.DEFAULT_BOLD //黑体字体类型 * Typeface.MONOSPACE

  • Android中使用Canvas绘制南丁格尔玫瑰图(Nightingale rose diagram)

    南丁格尔玫瑰图 在常规图表中实在很惊艳,但我初看没看懂,一查原来南丁格尔这么伟大,确实值得尊敬. 再仔细研究了下这种图的构成,发现原来就是把柱形图的柱形换成了扇形图的半径来表示,当然,变种有好多,我这只是说我理解的这种. 知道了其构成方式后就好实现了,依传入参数个数决定其扇形角度,依百分比决定其扇形的半径长度,然后就一切都水到渠成了. 漂亮的美图献上: 附上实现代码: package com.xcl.chart; /** * Canvas练习 * 自已画南丁格尔玫瑰图(Nightingale r

  • Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】

    本文实例讲述了Android编程实现canvas绘制柱状统计图功能.分享给大家供大家参考,具体如下: 这里实现了一个简单的柱状统计图,如下:   特点: 1.根据数据源自动计算每个条目的高度.宽度.间距,自动计算分度值. 2.当条目数较多时,可左右滑动查看全部内容,图形.文字同步滑动,并且松手后会渐渐的停下来(而不是立刻停下来). 代码: (1)核心代码:BarChartView.Java package com.sina.appbarchart; import android.app.Acti

  • Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】

    本文实例讲述了Android编程实现canvas绘制饼状统计图功能.分享给大家供大家参考,具体如下: 本例的目的是实现一个简单的饼状统计图,效果如下:    特点: 1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即: PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart); PieChartView.PieItemBean[] items = new PieChartView.PieItem

  • Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)

    本文实例讲述了Android编程开发之在Canvas中利用Path绘制基本图形的方法.分享给大家供大家参考,具体如下: 在Android中绘制基本的集合图形,本程序就是自定义一个View组件,程序重写该View组件的onDraw(Canvase)方法,然后在该Canvas上绘制大量的基本的集合图形. 直接上代码: 1.自定义的View组件代码: package com.infy.configuration; import android.content.Context; import andro

  • Android编程之canvas绘制各种图形(点,直线,弧,圆,椭圆,文字,矩形,多边形,曲线,圆角矩形)

    本文实例讲述了Android编程之canvas绘制各种图形的方法.分享给大家供大家参考,具体如下: 1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into

  • Android开发使用自定义View将圆角矩形绘制在Canvas上的方法

    本文实例讲述了Android开发使用自定义View将圆角矩形绘制在Canvas上的方法.分享给大家供大家参考,具体如下: 前几天,公司一个项目中,头像图片需要添加圆角,这样UI效果会更好看,于是写了一个小的demo进行圆角的定义,该处主要是使用BitmapShader进行了渲染(如果要将一张图片裁剪成椭圆或圆形显示在屏幕上,也可以使用BitmapShader来完成). BitmapShader类完成渲染图片的基本步骤如下: 1.创建BitmapShader类的对象 /** * Call this

  • Android使用Canvas绘制圆形进度条效果

    前言 Android自定义控件经常会用到Canvas绘制2D图形,在优化自己自定义控件技能之前,必须熟练掌握Canvas绘图机制.本文从以下三个方面对Canvas绘图机制进行讲解: 画布Canvas 画笔Paint 示例圆形进度条 画布Canvas 首先,来看一下Android官网对Canvas类的定义: The Canvas class holds the "draw" calls.To draw something, you need 4 basic components: A B

  • Android Canvas绘制文字横纵向对齐

    目录 1. 横向对齐(Align属性) 2. TextBound 3. 纵向对齐与绘制线 4. 总结 1. 横向对齐(Align属性) Align属性决定了使用该画笔时,相较于绘制点的水平对称方式,分别是LEFT.CENTER.RIGHT,对应的情况: 如最上方的文字及其框线所示,文字具有三个备选的初始绘制基点,Align属性将会指定这三个绿色的哪一个基点最终和绘制目标基点进行重合对齐. 红色的点就是我们在drawText()中填入的xy坐标参数,我们暂且将其称为目标基点(x,y)被确定之后,文

  • 详解微信小程序-canvas绘制文字实现自动换行

    在使用微信小程序canvas绘制文字时,时常会遇到这样的问题:因为canvasContext.fillText参数为 我们只能设置文本的最大宽度,这就产生一定的了问题.如果我们绘制的文本长度不确定或者我们希望文本超出自动换行或者用省略号表示,光靠这个API是无法完成的.下面本人就讲下我在开发中是如何解决这个问题的. 1 wxml代码 <canvas canvas-id="myCanvas" style="border: 1px solid;"/> 2 w

  • android canvas drawText()文字居中效果

    本文跟大家分享下我关于drawText()文字居中的方法. 先附上drawText()的方法说明 说实话当时看了这个,我也没明白这个x,y坐标到底表达的啥意思,还一直以为是绘制文字中心的坐标,后来发现这个理解是错误的 要想理解这个首先看张图 像图上这样安卓的文字绘制是相对于基线绘制的,也就是图中的红线,而top+bottom的长度就等于字体高度.即等于|top|+|bottom|绝对值 实际绘制的时候取决于基线上一个点来绘制文字,而这个点有三种分别对应为left,center,right如下图

  • Android Canvas drawText文字居中的一些事(图解)

    1.写在前面 在实现自定义控件的过程中,常常会有绘制居中文字的需求,于是在网上搜了一些相关的博客,总是看的一脸懵逼,就想着自己分析一下,在此记录下来,希望对大家能够有所帮助. 2.绘制一段文本 首先把坐标原点移动到控件中心(默认坐标原点在屏幕左上角),这样看起来比较直观一些,然后绘制x.y轴,此时原点向上y为负,向下y为正,向左x为负,向右x为正,以(0,0)坐标开始绘制一段文本: @Override public void draw(Canvas canvas) { super.draw(ca

  • JavaScript+Canvas实现文字粒子流特效

    目录 动手前思考 绘制文字 获取像素点位 渲染粒子 简单的动画效果 1.随机选择四个方向中的某一个方向,生成初始坐标 2.从初始位置运动到实际位置 3.点击文字炸开的特效 动手前思考 首先要在特定的位置生成粒子,要获取到canvas上像素的点位,通过canvas的getImageData函数我们可以得到canvas像素点的信息,获取像素点中透明度大于0的位置. 绘制文字 新建一个canvas画布,在画布上绘制任意的文字 ctx.font = "200px Arial"; ctx.fon

  • Android Canvas的drawText()与文字居中方案详解

    自定义View是绘制文本有三类方法 // 第一类 public void drawText (String text, float x, float y, Paint paint) public void drawText (String text, int start, int end, float x, float y, Paint paint) public void drawText (CharSequence text, int start, int end, float x, flo

随机推荐