2025年Android paint的drawText() 的正确使用方式

Android paint的drawText() 的正确使用方式最近项目需求做一个倒计时的功能 本想直接找一个第三方用的 结果需求有点不一样 我们是不计算天的 都用时 分 秒表示 可能会有 1021 59 59 这种奇葩出现 网上还真找不到类似的 就自己写了一个 然而发现 drawText 没有想象中的那么好用

大家好,我是讯享网,很高兴认识大家。

  最近项目需求做一个倒计时的功能,本想直接找一个第三方用的。结果需求有点不一样,我们是不计算天的,都用时:分:秒表示。可能会有1021:59:59这种奇葩出现,网上还真找不到类似的,就自己写了一个。然而发现drawText没有想象中的那么好用,网上找了很多资料都不太准确,这里是研究了几天的使用心得,在这里分享下。
  顺便将参考过的帖子都贴上来,如果我写的不好的话可以去参考一下这几位博主的。
  如何“任性”使用Android的drawText()
  Android Canvas drawText实现中文垂直居中
   Android ApiDemos示例解析(81):Graphics->Text Align

一、BaseLine

自定义一个类继承View,运行这一段代码看看

@Override protected void onDraw(Canvas canvas) { canvas.drawText("AItsuki的博客", 0,0,paint); }

讯享网

就像是这样,认真看actionbar的底边:
这里写图片描述
讯享网

二、getTextBounds

那怎么才能将画出来的文字贴合屏幕呢?
这就需要计算文字的最小包裹区域了,就是没有包含字间距和行间距的区域。
Paint提供了一个方法, getTextBounds()。
传入一个Rect对象可以获得文字的左上右下(相对于左上角0,0位置)和小宽度。
我们在构造中使用,然后看下log的打印。

讯享网public Test(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(0xff000000); paint.setTextSize(60); rect = new Rect(); paint.getTextBounds("0", 0, 1, rect); Log.e("rect", "left = " + rect.left + ", top = " + rect.top + ", right = " + rect.right + ", bottom = " + rect.bottom); Log.e("rect", "width = " + rect.width() +", height" +rect.height()); }

这里写图片描述

1. 贴合顶部

上面也说过,drawText("AItsuki的博客~",0, 0, Paint paint) 第三个参数y=0的位置其实就是baseline,而露出的一点点其实就是rect.bottom。很容易可以得出

当baseline = rect.height - rect.bottom的时候,就可以恰好将文字显示完全。
来校验下试试,运行下面代码:

@Override protected void onDraw(Canvas canvas) { paint.getTextBounds("AItsuki的博客", 0, 10, rect); canvas.drawText("AItsuki的博客", 0,rect.height() - rect.bottom ,paint); }

这里写图片描述

2. 贴合左边

1. 第一种

减去左边的边距。drawText(“007的博客~”,-rect.left , baseline, Paint paint);

2. 第二种

第二种:也是减去左边的边距,换种方式减而已,设置paint.textAlign为center从中间开始画

讯享网paint.setTextAlign(Paint.Align.CENTER); drawText("007",rect.width()/2 , baseline, Paint paint)

看下效果
这里写图片描述
这两种方法都有弊端,所以不推荐使用
如果是一次性画一段文字或者每次只画一个字拼起来没问题,
但是两个字两个字的画就不太好,因为每个字的宽度都不一样,会导致字和字之间的距离不一致。

3. 居中

public Test(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(0xff000000); paint.setTextSize(60); // ======================== rect = new Rect(); paint.getTextBounds("0", 0, 1, rect); numberBaseline = rect.height() - rect.bottom; int numberHeight = rect.height(); paint.getTextBounds(".",0,1,rect); pointBaseline = rect.height() -rect.bottom; int pointHeight = rect.height(); pointBaseline += numberHeight*0.5f - pointHeight*0.5f; } @Override protected void onDraw(Canvas canvas) { canvas.drawText("0", 0 , numberBaseline ,paint); canvas.drawText(".", paint.measureText("0") ,pointBaseline ,paint); canvas.drawText("0", paint.measureText("0.") , numberBaseline ,paint); }

这里写图片描述

三、rect.width()和 paint.measureText()

前者是获取最小包裹区域的宽度,后者是获取加上左右边距的宽度。
推荐使用后者,因为前者0, 各个数字的宽高不一致,onMeasure的时候不好测量,会出问题。
非要用rect.width()的话要分开计算宽高,4是最宽的但是也是最矮,0是最高的但是宽度不够,所以干脆用measureText就行了。

小讯
上一篇 2025-01-08 08:04
下一篇 2025-01-10 10:44

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/19893.html