绘制文字
1.0
绘制文字其实是使用Canvas当中的drawText()函数来绘制的:
class UsePaint @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
val paint: Paint
init {
paint = Paint()
paint.color = Color.RED
paint.textSize = sp(22).toFloat()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawText("hello", 50f, 200f, paint)
}
}
在drawText()函数中有四个参数,需要说明的是第二参数 X 和第三个参数 Y。表示文字绘制的原点坐标。需要注意的是绘制文字的原点和普通view的原点是不一样的。普通view原点都是在view的左上角,而文字的原点则是在基准线上,大概是在下图中蓝色圆点位置:
总结一下就是y表示的是基准线,x表示文字绘制的起始位置,所以一旦文字的长度确定了,就可以绘制出文字。
其实文字的绘制也是要画一份矩形的区域绘制的,比如这样:
在Paint类中有一个函数:setTextAlign()。这个函数的作用是来确定所要绘制文字矩形的相对位置,也就是x的位置。所需要的参数有三个取值,下面分别来感受一下区别:
Paint.Align.LEFT
Paint.Align.CENTER
Paint.Align.RIGHT
分别对应下图中x在矩形中的位置:
默认是LEFT。当为CENTER的时候,x是矩形下条边的中心点,而绘制是在矩形当中的,故左半边就出了屏幕就看不到了。RIGHT同理,但结果是全部出去屏幕了。
2.0
其实在绘制文字的时候不止一条基准线,还有其他四条线,如下图所示:
上图中从上到下一共5条线。其中第一条和最后一条为top和bottom,分别表示可绘制的最高高度和最低高度所在线。第二条和第四条为ascent和descent,分别表示为绘制单个字符时,字符应当的最高高度和最低高度所在线。剩下当中的那一条就是前面提过的基准线。
基准线是在调用drawText()函数是传入的y值决定的。剩下的4条线则可以通过FontMetrics类计算出来。
val metrics = paint.fontMetrics // 等价于java的paint.getMetrics()
metrics.ascent
metrics.descent
metrics.top
metrics.bottom
FontMetrics中的这四个属性是具体的数值,和上面图片中的四条线不是一个概念,这四个属性是通过计算得来的。
ascent = ascent线的y坐标-baseLine的y坐标,也就是说如果直接取出来的数值是负数。同理我们可以计算其他的三个属性值的计算方式:
descent = descent线的y坐标-baseLine的y坐标,值为正数
top = top线的y坐标-baseLine的y坐标,值为负数
bottom = bottom线的y坐标-baseLine的y坐标,值为正数
知道了这个我们就可以很容易的计算出每条线的y坐标,并画出来:
canvas.drawLine(baseX, metrics.ascent + baseY, 800f, metrics.ascent + baseY, paint)
canvas.drawLine(baseX, metrics.descent + baseY, 800f, metrics.descent + baseY, paint)
canvas.drawLine(baseX, metrics.top + baseY, 800f, metrics.top + baseY, paint)
canvas.drawLine(baseX, metrics.bottom + baseY, 800f, metrics.bottom + baseY, paint)
2.1
- 1、求字符串所占区域的高度和宽度
根据上面的知识,很容易得到字符串所占区域的高:
val metrics = paint.fontMetrics
val top = baseY + metrics.top
val bottom = baseY + metrics.bottom
val textHeight = top + bottom
宽度也是很容易得到的:
val textWidth = paint.measureText("bigpig")
- 2、最小矩形
最小矩形是通过系统函数来获取的:
public void getTextBounds(String text, int start, int end, Rect bounds) {
- text就是要测量最小矩形的字符串
- start是测量的起始字符的在字符串中的索引
- end是要测量的字符长度
-
bounds用于接收测量结果
可是如果下面把这个矩形画出来却有点匪夷所思:
上面紫色的是ToolBar,下面黑色的细长矩形就是画出来的矩形,明显位置不对,大小也不对。大小不对是因为有一部分不在屏幕内,出去了。这是因为没有给getTextBounds()传递基准线位置,系统就会默认的以(0,0)点来作为基线来获取最小矩形。所以要获取真实的矩形位置就需要手动去加上基准位置:
val rect = Rect()
paint.getTextBounds("bigpig", 0, 6, rect)
rect.top = (rect.top + baseY).toInt()
rect.bottom = (rect.bottom + baseY).toInt()
rect.left = (rect.left + baseX).toInt()
rect.right = (rect.right + baseX).toInt()
canvas.drawRect(rect, paint)
3.0
Paint的一些常用函数:
-
reset() 重置画笔
-
setColor(int color) 给画笔设置颜色
-
setARGB(int a, int r, int g,int b) 设置颜色,只不过是按照A R G B分开设置
-
setAlpha (int alpha) 给画笔设置透明度
-
setStyle(Paint .Style style) 给画笔设置样式,有三种:FILL,STROKE,FILL_AND_STROKE
-
setAntiAlias(boolean aa) 设置是否抗锯齿
下面是不开启抗锯齿的效果,方法之后就是这样的。假如开了抗锯齿,那么效果就会圆滑很多
-
setStrokeWidth(float width) 设置画笔宽度
-
setStrokeMiter (float miter) 设置画笔的倾斜度
-
setPathEffect(PathEffect effect) 设置路径样式
-
setStrokeCap(Paint.Cap cap) 设置线帽样式 有三种:ROUND、SQUARE、BUTT
paint.strokeCap = Paint.Cap.ROUND
canvas.drawLine(100f, 50f, 500f, 50f, paint)
paint.strokeCap = Paint.Cap.SQUARE
canvas.drawLine(100f, 120f, 500f, 120f, paint)
paint.strokeCap = Paint.Cap.BUTT
canvas.drawLine(100f, 190f, 500f, 190f, paint)
- setStrokeJoin(Paint.Join join) 设置路径的转角样式,有三种:BEVEL,MITER,ROUND
val path = Path()
path.moveTo(100f, 100f)
path.lineTo(450f, 100f)
path.lineTo(100f, 300f)
canvas.drawPath(path, paint)
可以看到默认是MITER样式
- setDither(boolean dither) 设置是否抗抖动 图像颜色在渐变的时候,会出现类似马赛克的效果,为了让色彩过度不那么生硬,于是将相邻像素之间的颜色值进行中和,以呈现一种更细腻的过度效果。
- setTextSize(float textSize) 设置文字大小 单位为像素
- setFakeBoldText(boolean fakeBoldText) 设置是否为粗体文字
- setUnderlineText(boolean underlineText) 给文字设置下划线
- setStrikeThruText(boolean strikeThruText) 设置带有删除线效果
- setTextAlign(Paint. Align align) 设置文字绘制点位置
- setTextScaleX(float scaleX) 设置文字水平拉伸
- setTextSkewX(float skewX) 设置字体水平倾斜度
- setTypeface(Typeface typeface) 设置文字样式
- setLinearText(boolean linearText) 设置是否打开线性文本标识 文本想快速绘制出来,需要缓存起来,但是就会占用内存。如果设置为true,则不缓存,省内存,但是绘制速度会慢一些
- setSubpixelText(boolean subpixelText) 是否打开亚像素设置来绘制文本 设置为true,可以增强文本显示清晰度,但是会消耗计算机性能,因为它是通过程序在屏幕的两个像素之间插入的非物理的像素,需要计算。
网友评论