一、如何绘制文字,并居中显示
现在我们自定义一个View,绘制一个圆环,并在圆环中间画一串文字
private val paint = Paint()
private val content = "abc"
private var bounds = Rect()
init {
paint.style = Paint.Style.STROKE
paint.strokeWidth = 2f.dp
paint.textSize = 50f.dp
paint.textAlign = Paint.Align.CENTER
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.translate(width / 2f, height / 2f)
canvas.drawCircle(0f, 0f, 100f.dp, paint)
paint.style = Paint.Style.FILL
paint.getTextBounds(content, 0, content.length, bounds)//获取文字内容的边界
canvas.drawText(
content,
0f,
0f - (bounds.top + bounds.bottom) / 2, //y值需要减去1/2字的占用高度
paint
)
}
生成的效果如下:
二、动态文字如何居中
上面的写法只是针对静态文字的绝对居中,但如果文字换成“abcq”,那么其中的“abc”就会略微向上移动,如果是动态变化的文字,就会造成文字的高低动态变化,显得很乱,那么动态变化的文字如何居中呢
1. 绘制文字时的5条基准线
借用一张网图:
Top:最高字符到baseline的值,即ascent的最大值,为负数
Ascent:字符最高处到baseline的值,为负数
Baseline:基线,字符在TextView中的基准点
Descent:字符最低处到baseline的值,为正数
Bottom:最低字符到baseline的值,即descent的最大值,为正数
2. 调整文字居中
val metrics = FontMetrics()
paint.getFontMetrics(metrics)
canvas.drawText(
content,
0f,
0f - (metrics.ascent + metrics.descent) / 2, //y值需要减去实际文字高度一半
paint
)
通过使用ascent和descent,来确定动态文字的y值
三、文字贴边
根据UI的实际要求
上端贴边有三种方式,分别是利用TextBounds的top、FontMatrics的top或者ascent 三个值,来去掉边。
下端贴边有三种方式,分别是利用TextBounds的bottom、FontMatrics的bottom或者descent 三个值,来去掉边。
左端贴边用TextBounds的left。
右端贴边用TextBounds的right。
四、多行文字绘制
1. 纯文字
自动换行可以使用StaticLayout,Android的TextView也是用的StaticLayout
2. 图文
图文混排时,需要让文字避开图片,所以不能用StaticLayout,需要我们自行断行
Paint.class
//第一次断行时可以用
public int breakText(String text, boolean measureForwards,
float maxWidth, float[] measuredWidth)
//从第二行开始断行时使用
public int breakText(CharSequence text, int start, int end,
boolean measureForwards,
float maxWidth, float[] measuredWidth)
同时我们需要知道每一行的y值: - fontMatrics.top + lineCount(行数) * paint.fontSpacing