美文网首页
关于把文本绘制到控件中间的问题

关于把文本绘制到控件中间的问题

作者: 飞奔吧牛牛 | 来源:发表于2020-08-10 23:47 被阅读0次

    只需要搞懂这两个方法。别看源码了,这两个方法调到最后都跑native那边去了。

    Paint.getFontMetricsInt();

    这个方法提供了文字排版的几个重要数据,top,ascent,descent,bottom,leading。最后一个leading不知道什么用,据说和额外边距有关,即上一行text的bottom距下一行text的top的距离,这里暂且用不到。

    绘制文本时,调用canvas.drawText(String text, float x, float y, Paint paint);
    值得注意的是,这里的x,y是文字的左下角的某个位置,具体如下图所示:


    image.png

    看到了吗,就那个小红点。


    image.png
    这里的y所在的线大家都叫它baseline。
    现在关于Paint.getFontMetricsInt();所得到的这几条线全画出来是这个样子。多了个‘a’?嗯,我故意的。
    image.png

    这五条线依次是top,ascent,baseline,descent,bottom。
    其中ascent和descent之间的区域是常见字符的范围,中文都是方块字,英文也还算规矩,一般不会超出这个区域。
    这样文字所占的高度就可以拿到了:descent-ascent。也有人用bottom-top的。

    Paint.getTextBounds(String text, int start, int end, Rect bounds);

    刚开始拿到这个bounds,看到里面的数据也是一脸懵比。其实,它也以原点为基础,得到文字绝对大小的所在区域。


    image.png

    这两个方法研究透彻之后,要把一个文本绘制在一个区域的中间,要解决的就是一个数学问题了,即计算原点应该放到哪里。这里直接给出代码吧。

    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
    
            drawText(canvas, width, height);
        }
    
        private void drawText(Canvas canvas, int width, int height) {
            //获取起点x坐标
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            float startX = (width - bounds.width()) / 2.0f;
            //获取起点y坐标
            Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
            int baseline = (height - fontMetrics.descent - fontMetrics.ascent) / 2;
            //绘制text
            canvas.drawText(mText, startX, baseline, mPaint);
            
            //绘制baseline
            canvas.drawLine(0, baseline, width, baseline, mPaint);
    
            //绘制top
            float top = baseline + fontMetrics.top;
            canvas.drawLine(0, top, width, top, mPaint);
            //绘制ascent
            float ascent = baseline + fontMetrics.ascent;
            canvas.drawLine(0, ascent, width, ascent, mPaint);
            //绘制descent
            float descent = baseline + fontMetrics.descent;
            canvas.drawLine(0, descent, width, descent, mPaint);
            //绘制bottom
            float bottom = baseline + fontMetrics.bottom;
            canvas.drawLine(0, bottom, width, bottom, mPaint);
    
            //绘制bounds区域
            float rectLeft = startX + bounds.left;
            float rectRight = startX + bounds.right;
            float rectTop = baseline + bounds.top;
            float rectBottom = baseline + bounds.bottom;
            //top线
            canvas.drawLine(rectLeft, rectTop, rectRight, rectTop, mPaint);
            //left线
            canvas.drawLine(rectLeft, rectTop, rectLeft, rectBottom, mPaint);
            //right线
            canvas.drawLine(rectRight, rectTop, rectRight, rectBottom, mPaint);
            //bottom线
            canvas.drawLine(rectLeft, rectBottom, rectRight, rectBottom, mPaint);
    
            //绘制原点
            mPaint.setStrokeWidth(3);
            mPaint.setColor(Color.RED);
            canvas.drawPoint(startX, baseline, mPaint);
        }
    

    相关文章

      网友评论

          本文标题:关于把文本绘制到控件中间的问题

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