Android Advance 9: top, bottom, ascent, descent, baseline of TextView Drawing Principles

Keywords: Android

top,bottom,ascent,descent,baseline

Let's start with a picture:

When the text is drawn, the top, bottom, ascent, descent and baseline values will be confirmed according to the current font size and other information. These values will ultimately affect the display position of the font in TextView.
These values can be obtained by getPaint().getFontMetricsInt().

  • Baseline: Baseline, the base point of a character in TextView. The drawing of a character is done through this base point. The value of top, bottom, ascent, descent is obtained from this zero point. Top and ascent above baseline are negative, and bottom and descent below baseline are positive.

  • top: refers to the value from the highest character to the base, i.e. the maximum ascent, which is a negative number.

  • ascent: The distance from the top of the base line to the top of the character, negative

  • bottom: refers to the value from the lowest character to the base, i.e. the maximum descent, which is a positive number.

  • descent: The distance from the base line to the lowest point of the character, which is a positive number

test

I customized a NonSpace TextView:

@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 Component properties
         */
        Ln.e("textview bottom:" + getBottom() +
                " \ntop:" + getTop() +
                " \nbaseline:" + getBaseline());


    }

Add:

    <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" />

The print result is:

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

 textview bottom:37
 top:0
 baseline:26

It is shown as follows:

Find that the top and bottom borders of TextView take up a lot of space, and sometimes want to remove them. Here's a simple way:

Remove the top and bottom borders of TextView

Generally, when the android:layout_height of TextView is set to wrap_content, if android:lineSpacingExtra and android:lineSpacingMultiplier are not set, the height of TextView is: (bottom - top)

Take the example above, TextView's high 37, font's bottom - top = 11 - (-25) = 37,

Generally speaking, the space between top and ascent and between bottom and descent are not needed.
So you can rewrite TextView to remove these two spaces:

1. Rewrite the measurement method by subtracting the height of the upper and lower borders from the height of the measurement.

@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. Rewrite the drawing method and move the drawing coordinates up (ascent - top)

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

The results are as follows:

Posted by DigitHeads on Thu, 20 Dec 2018 11:12:05 -0800