美文网首页
FontMetrics

FontMetrics

作者: iyifei | 来源:发表于2019-01-10 19:21 被阅读22次

    Google文档中的描述:

    /**
    * Class that describes the various各种 metrics指标 for a font at a given text size.
    * Remember, Y values increase going down, so those values will be positive正数,
    * and values that measure distances距离 going up will be negative负数. This class
    * is returned by getFontMetrics().
    */
    public static class FontMetrics {
       //The maximum distance above the baseline for the tallest glyph in the font at a given text size.
       public float   top;
       //【字符顶部】The recommended推荐的 distance above the baseline for singled spaced text.
       public float   ascent;
       //【字符底部】The recommended distance below the baseline for singled spaced text.
       public float   descent;
       //The maximum distance below the baseline for the lowest glyph in the font at a given text size.
       public float   bottom;
       //【字符行间距】The recommended additional额外的 space to add between lines两行之间 of text.
       public float   leading;
    }
    

    该类描述给定文本大小的字体的各种度量。记住,Y值向下增加,所以这些值为正值,测量向上距离的值为负值。此类由GetFontMetrics()返回。

    网上找的各种模型图

    要点如下:

    • 基准点是baseline
    • Ascent是baseline之上至字符最高处的距离
    • Descent是baseline之下至字符最低处的距离
    • Leading文档说的很含糊,其实是上一行字符的descent到下一行的ascent之间的距离
    • Top指的是指的是最高字符到baseline的值,即ascent的最大值
    • bottom指的是最下字符到baseline的值,即descent的最大值
      为了帮助理解,我特此搜索了不同的示意图。对照示意图,会很容易理解FontMetrics的参数。
    图1.png 图2.png 图3.png 图4.png 图5.png 图6.png

    Paint的ascent和descent方法--算高度

    这两个是native方法

    //Return the distance above (negative) the baseline (ascent) based on the current typeface字体 and text size.
    public native float ascent();
    //Return the distance below (positive) the baseline (descent) based on the current typeface and text size.
    public native float descent();
    

    可以通过 mPaint.ascent()+ mPaint.descent() 获取文字高度

    Paint的measureText方法--获取宽度

    image
    /**
     * Return the width of the text.
     *
     * @param text  The text to measure. Cannot be null.
     * @param start The index of the first character to start measuring
     * @param end   1 beyond the index of the last character to measure
     * @return      The width of the text
     */
    public float measureText(String text, int start, int end) {
        if (text == null) throw new IllegalArgumentException("text cannot be null");
        if ((start | end | (end - start) | (text.length() - end)) < 0) throw new IndexOutOfBoundsException();
        if (text.length() == 0 || start == end) return 0f;
        if (!mHasCompatScaling) return (float) Math.ceil(native_measureText(text, start, end, mBidiFlags));
    
        final float oldSize = getTextSize();
        setTextSize(oldSize*mCompatScaling);
        float w = native_measureText(text, start, end, mBidiFlags);
        setTextSize(oldSize);
        return (float) Math.ceil(w*mInvCompatScaling);
    }
    
    

    通过这个方法即可以轻松的获取到文字的的宽度

    Paint的getTextBounds方法--获取边界

    image
    /**
     * Return in bounds (allocated by the caller 由调用者分配) the smallest最小的 rectangle that
     * encloses围起来 all of the characters, with an implied origin默认的起始位置 at (0,0).
     * @param text  String to measure and return its bounds
     * @param start Index of the first char in the string to measure
     * @param end   1 past the last char in the string measure
     * @param bounds Returns the unioned bounds of all the text. Must be allocated by the caller.
     */
    public void getTextBounds(String text, int start, int end, Rect bounds) {
        if ((start | end | (end - start) | (text.length() - end)) < 0)  throw new IndexOutOfBoundsException();
        if (bounds == null) throw new NullPointerException("need bounds Rect");
        nativeGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
    }
    

    这个方法需要提供一个参数 Rect 矩形区域,这个方法将文字的区域传递到 Rect

    Paint的获取

    比如对于TextView,要通过TextView的getPaint()得到Paint,而不能new一个或者拿其他不相干的Paint

    /**
     * @return the base paint used for the text.  Please use this only to
     * consult查阅 the Paint's properties属性 and not to change them.
     */
    public TextPaint getPaint() {
        return mTextPaint;
    }
    

    如果是在自定义View 中,则可以直接通过Paint调用相关方法去获取文字的宽高等信息

    测试代码

    public class MainActivity extends Activity {
    
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            String text = "aA bB fF gG";
    
            TextView tv_info = new TextView(this);
    
            tv_info.setTextColor(Color.BLUE);
    
            tv_info.setBackgroundColor(0x5500ff00);
    
            tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
    
            tv_info.setText(text);
    
            setContentView(tv_info);
    
            tv_info.measure(0, 0);//必须手动调用测量方法,否则getMeasuredHeight获取不到值。另外,即使测量过了getHeight也获取不到值
    
            Paint mPaint = tv_info.getPaint();
    
            Log.i("bqt", "ascent()的值为" + mPaint.ascent() + ",descent()的值为" + mPaint.descent());//-33.398438, 8.7890625
    
            Log.i("bqt", "字符的高度为" + (-mPaint.ascent() + mPaint.descent()) + ",字符的长度为" + mPaint.measureText(text));//42.1875,190.0
    
            Log.i("bqt", "测量的高度为" + tv_info.getMeasuredHeight() + ",测量的宽度为" + tv_info.getMeasuredWidth());//49,190
    
            Rect mRect = new Rect();
    
            mPaint.getTextBounds(text, 0, text.length(), mRect);
    
            Log.i("bqt", "字符的边界为" + mRect.left + "," + mRect.top + "," + mRect.right + "," + mRect.bottom);//1,-28,187,8
    
            Log.i("bqt", "字符的高度为" + (mRect.bottom - mRect.top) + ",字符的长度为" + (mRect.right - mRect.left));//36,186
    
        }
    
    }
    

    相关文章

      网友评论

          本文标题:FontMetrics

          本文链接:https://www.haomeiwen.com/subject/etqzrqtx.html