Android进阶九:TextView绘制原理之top,bottom,ascent,descent,baseline

top,bottom,ascent,descent,baseline

先来看一张图:

Android进阶九:TextView绘制原理之top,bottom,ascent,descent,baseline_第1张图片

文字在绘制的时候,会根据当前的字体,字体大小等信息,确认top,bottom,ascent,descent,baseline的值,这些值会最终影响到字体在TextView中的显示位置,
通过getPaint().getFontMetricsInt()可以获取到这些值

  • baseline:基准点,字符在TextView中的基准点,字符的绘制就是通过这个基准点来绘制的,相当于字符的零点,top,bottom,ascent,descent的值就是以这个为零点来得到的,在baseline上面的top和ascent是负数,在baseline下面的bottom和descent是正数

  • top:是指的是最高字符到baseline的值,即ascent的最大值,为负数

  • ascent:是baseline之上至字符最高处的距离,为负数

  • bottom:是指最低字符到baseline的值,即descent的最大值,为正数

  • descent:是baseline之下至字符最低处的距离,为正数

测试

我自定义了一个NonSpaceTextView:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Ln.e("font bottom:" + getPaint().getFontMetricsInt().bottom +
                "  \ndescent:" + getPaint().getFontMetricsInt().descent +
                " \nascent:" + getPaint().getFontMetricsInt().ascent +
                " \ntop:" + getPaint().getFontMetricsInt().top +
                " \nbaseline:" + getBaseline());

        /**
         * TextView组件的属性
         */
        Ln.e("textview bottom:" + getBottom() +
                " \ntop:" + getTop() +
                " \nbaseline:" + getBaseline());


    }

layout中加入:

    <com.biyou.view.NonSpaceTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="6ms jkÖÄ"
        android:textColor="@color/clr_black"
        android:textSize="25sp"
        android:background="#FFFF00FF"
        android:layout_gravity="center_horizontal"
        android:id = "@+id/id_value"
        android:textStyle="bold" />

打印结果是:

font bottom:11 
 descent:5 
 ascent:-25 
 top:-26
 baseline:26 

 textview bottom:37
 top:0
 baseline:26

显示如下:

这里写图片描述

发现TextView的上下边框占据很大的空间,有时候想把他们去掉,下面是个简单的方法:

去掉TextView的上下边框

一般当TextView的android:layout_height设置为wrap_content的时候,若未设置 android:lineSpacingExtra和android:lineSpacingMultiplier,TextView的高为:(bottom - top)

拿上面的例子TextView的高位37,font的bottom - top = 11 - (-25) = 37,

一般地,top到 ascent之间的空间,和bottom和descent之间的空间都是用不到的,
所以可以重写TextView来去掉这两个空间:

1.重写测量方法,把测量的高度减去上下两个边框的高度:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(heightMode == MeasureSpec.AT_MOST)
        {
            int deltaHeight = (getPaint().getFontMetricsInt().ascent - getPaint().getFontMetricsInt().top + getPaint().getFontMetricsInt().bottom - getPaint().getFontMetricsInt().descent);
            setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() - deltaHeight);
        }
    }

2.重写绘制方法,把绘制坐标往上移(ascent - top)的距离

    @Override
    protected void onDraw(Canvas canvas) {
        int topDelta = (getPaint().getFontMetricsInt().ascent - getPaint().getFontMetricsInt().top);
       setTop(-topDelta);
        super.onDraw(canvas);
    }

效果如下:

这里写图片描述

你可能感兴趣的:(进阶)