canvas drawText文字垂直居中
来源:互联网 发布:淘宝闲鱼官方网站 编辑:程序博客网 时间:2024/05/09 16:35
原文:http://blog.csdn.net/hursing/article/details/18703599
关键代码
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2; mPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(infoToShow, textRect.centerX(), baseline, mPaint);
原理性解释:(以下为转载内容)
目标:
把中文字符绘制到目标矩形的居中位置。
问题:
Android的Canvas绘图,drawText里的origin是以baseline为基准的,直接以目标矩形的bottom传进drawText,字符位置会偏下。这样写代码:
@Overridepublic void onDraw (Canvas canvas) { Rect targetRect = new Rect(50, 50, 1000, 200); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeWidth(3); paint.setTextSize(80); String testString = "测试:ijkJQKA:1234"; paint.setColor(Color.CYAN); canvas.drawRect(targetRect, paint); paint.setColor(Color.RED); canvas.drawText(testString, targetRect.left, targetRect.bottom, paint);}
会得到难看的结果:
找方案:
首先自己动手做实验,自己定一个baseline,然后把文字画上去,再画上FontMetrics的几条线。FontMetrics里是字体图样的信息,有float型和int型的版本,都可以从Paint中获取。它的每个成员数值都是以baseline为基准计算的,所以负值表示在baseline之上。实验代码:
@Overridepublic void onDraw (Canvas canvas) { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeWidth(3); paint.setTextSize(80); FontMetricsInt fmi = paint.getFontMetricsInt(); String testString = "测试:ijkJQKA:1234"; Rect bounds1 = new Rect(); paint.getTextBounds("测", 0, 1, bounds1); Rect bounds2 = new Rect(); paint.getTextBounds("测试:ijk", 0, 6, bounds2); // 随意设一个位置作为baseline int x = 200; int y = 400; // 把testString画在baseline上 canvas.drawText(testString, x, y, paint); // bounds1 paint.setStyle(Style.STROKE); // 画空心矩形 canvas.save(); canvas.translate(x, y); // 注意这里有translate。getTextBounds得到的矩形也是以baseline为基准的 paint.setColor(Color.GREEN); canvas.drawRect(bounds1, paint); canvas.restore(); // bounds2 canvas.save(); paint.setColor(Color.MAGENTA); canvas.translate(x, y); canvas.drawRect(bounds2, paint); canvas.restore(); // baseline paint.setColor(Color.RED); canvas.drawLine(x, y, 1024, y, paint); // ascent paint.setColor(Color.YELLOW); canvas.drawLine(x, y+fmi.ascent, 1024, y+fmi.ascent, paint); // descent paint.setColor(Color.BLUE); canvas.drawLine(x, y+fmi.descent, 1024, y+fmi.descent, paint); // top paint.setColor(Color.DKGRAY); canvas.drawLine(x, y+fmi.top, 1024, y+fmi.top, paint); // bottom paint.setColor(Color.GREEN); canvas.drawLine(x, y+fmi.bottom, 1024, y+fmi.bottom, paint);}
获得结果:
红线是baseline,最上面的灰线是FontMetrics.top,最下面的绿线是FontMetrics.bottom。(绿色的bottom和蓝色的descent非常接近)
从图中可知,字符本身是在灰线和绿线之间居中的,知道这个就好办了。网上说的使用paint.getTextBounds的方法都不靠谱,可以看到对一个“测”字和6个字得到的bounds是不同的,图中的矩形能很好地表示这个函数得到的是字符的边界,而不是字体的边界。
FontMetrics.top的数值是个负数,其绝对值就是字体绘制边界到baseline的距离。
所以如果是把文字画在 FontMetrics高度的矩形中, drawText就应该传入 -FontMetrics.top。
要画在targetRect的居中位置,baseline的计算公式就是:
targetRect.centerY() - (FontMetrics.bottom - FontMetrics.top) / 2 - FontMetrics.top
优化后即:
(targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2
解决:
所以最开始的代码应该改成(顺便加入水平居中):
@Overridepublic void onDraw (Canvas canvas) { Rect targetRect = new Rect(50, 50, 1000, 200); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeWidth(3); paint.setTextSize(80); String testString = "测试:ijkJQKA:1234"; paint.setColor(Color.CYAN); canvas.drawRect(targetRect, paint); paint.setColor(Color.RED); FontMetricsInt fontMetrics = paint.getFontMetricsInt(); // 转载请注明出处:http://blog.csdn.net/hursing int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2; // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX() paint.setTextAlign(Paint.Align.CENTER); canvas.drawText(testString, targetRect.centerX(), baseline, paint);}
效果(点击查看大图):
还可以去看看android sdk源码,
$android4.2/frameworks/base/corej/ava/android/text/BoringLayout.java是TextView画文字的算法
- canvas drawText文字垂直居中
- Android 史上最简单的实现Canvas drawText文字垂直居中
- android canvas drawText()文字居中
- Android Canvas drawText()文字居中
- android canvas drawText()文字居中
- Android Canvas drawText实现中文垂直居中
- Android Canvas drawText实现中文垂直居中
- Android Canvas drawText实现中文垂直居中
- Android Canvas drawText实现中文垂直居中
- android canvas drawText实现文本垂直居中
- Android Canvas drawText实现中文垂直居中
- Android Canvas drawText实现中文垂直居中
- 安卓开发——实现canvas.drawText文字水平且垂直居中
- Android 中Canvas.drawText实现文字居中
- canvas.drawText文字居中(备忘)
- canvas.DrawText让文字真正居中显示
- Android Canvas.drawText垂直居中问题三种情况
- CDC::DrawText垂直居中
- C 可变参数的使用
- Git生成密钥
- I2C总线学习之四--TUNER(MXL60X)
- PHP 7.0.0 正式发布,速度是 PHP 5.6 的两倍
- opengl版本更新和绘制方式
- canvas drawText文字垂直居中
- 263.[LeetCode]Ugly Number
- java自定义异常以及异常的使用
- Hadoop 2.2.0 集群搭建
- 前端构建:Less入了个门
- 数据结构实验之链表二:逆序建立链表
- 【leetcode】7. Reverse Integer
- Java使用udp传输方式进行网络通信
- 怎么成为java的高手?