Paint的基本使用

2020-06-30  本文已影响0人  echoSuny

绘制文字

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条线。其中第一条和最后一条为topbottom,分别表示可绘制的最高高度和最低高度所在线。第二条和第四条为ascentdescent,分别表示为绘制单个字符时,字符应当的最高高度和最低高度所在线。剩下当中的那一条就是前面提过的基准线。
基准线是在调用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

        val metrics = paint.fontMetrics
        val top = baseY + metrics.top
        val bottom = baseY + metrics.bottom
        val textHeight = top + bottom

宽度也是很容易得到的:

        val textWidth = paint.measureText("bigpig")
public void getTextBounds(String text, int start, int end, Rect bounds) {
  1. text就是要测量最小矩形的字符串
  2. start是测量的起始字符的在字符串中的索引
  3. end是要测量的字符长度
  4. 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的一些常用函数:

        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)
        val path = Path()
        path.moveTo(100f, 100f)
        path.lineTo(450f, 100f)
        path.lineTo(100f, 300f)
        canvas.drawPath(path, paint)

可以看到默认是MITER样式

上一篇 下一篇

猜你喜欢

热点阅读