画布的drawText()

作者: Small_Cake | 来源:发表于2019-08-16 16:32 被阅读0次

    参考:https://blog.csdn.net/harvic880925/article/details/50423762

    一、通过基线确定起点

    void drawText(String text, float x, float y, Paint paint)

    • 关键点:y的位置是文字的基线位置,而不是画其他图形的左上角
            int baseLineX = 20 ;
            int baseLineY = 200;
            int baseLineY2 = 300;
            //画基线
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);
            canvas.drawLine(baseLineX, baseLineY2, 3000, baseLineY2, paint);
            //写文字
            paint.setColor(Color.BLACK);
            paint.setTextSize(80); //以px为单位
            canvas.drawText("A a B b C c D d E e F f G g", baseLineX, baseLineY, paint);
            canvas.drawText("H h I i J j K k L l M m N n", baseLineX, baseLineY2, paint);
    
    个别小写字母低于基线

    paint.setTextAlign(Paint.Align)确定位置

    • 关键点,这里的位置是说的起点x,y相对于文字的位置,而不是要绘制的文字对应起点x,y的位置,这个有点反人类。相对位置是根据所要绘制文字所在矩形来计算的
            //画基线
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            canvas.drawLine(baseLineX, baseLineY, 2000, baseLineY, paint);
            canvas.drawLine(baseLineX, baseLineY+100, 2000, baseLineY+100, paint);
            canvas.drawLine(baseLineX, baseLineY+200, 2000, baseLineY+200, paint);
            canvas.drawLine(x, 0, x, 2000, paint);
            //写文字
            paint.setColor(Color.DKGRAY);
            paint.setTextSize(80); //以px为单位
            paint.setTextAlign(Paint.Align.LEFT);//起点x,y在文字的左边
            canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY, paint);
            paint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY+100, paint);
            paint.setTextAlign(Paint.Align.RIGHT);
            canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY+200, paint);
    
    左中右

    二、drawText的四线格与FontMetrics

    • top: 可绘制的最高高度所在线
    • ascent: 系统建议的,绘制单个字符时,字符应当的最高高度所在线
    • baseLine:基线,字符底部对其的基准线
    • descent:系统建议的,绘制单个字符时,字符应当的最低高度所在线
    • bottom: 可绘制的最低高度所在线

    baseLine可以通过drawText(String text, float x, float y, Paint paint)中的y来确定,那么其他四条线就需要用到FontMetrics,其中最后一个leading是指在文本行之间间隙

        public static class FontMetrics {
            public float   top;
            public float   ascent;
            public float   descent;
            public float   bottom;
            public float   leading;
        }
    

    这四条线的高度计算:

    • ascent = ascent线y坐标 - baseline线y坐标;
    • descent = descent线y坐标 - baseline线y坐标;
    • top = top线y坐标 - baseline线y坐标;
    • bottom = bottom线y坐标 - baseline线y坐标;
      但是由于FontMetrics里面四个位置的值是相对于baseLine计算的,所以要得到正真的对应值计算方法:
    • top线Y坐标 = baseline线的y坐标 + fontMetric.top;//fontMetric.top为负数
    • ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;//fontMetric.ascent为负数
    • descent线Y坐标 = baseline线的y坐标 + fontMetric.descent;//fontMetric.descent为负数
    • bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom;//fontMetric.bottom为正数
      通过画笔获取FontMetrics
            int baseLineY = 900;
            int baseLineX = 0 ;
            Paint paint = new Paint();
            //写文字
            paint.setColor(Color.BLACK);
            paint.setAntiAlias(true);
            paint.setTextSize(300); //以px为单位
            paint.setStrokeWidth(3);
            canvas.drawText("S C g j", baseLineX, baseLineY, paint);
            //计算各线在位置
            Paint.FontMetrics fm = paint.getFontMetrics();
            float ascent = baseLineY + fm.ascent;
            float descent = baseLineY + fm.descent;
            float top = baseLineY + fm.top;
            float bottom = baseLineY + fm.bottom;
            //画top
            paint.setColor(Color.RED);
            canvas.drawLine(baseLineX, top, 2000, top, paint);
            //画ascent
            paint.setColor(Color.YELLOW);
            canvas.drawLine(baseLineX, ascent, 2000, ascent, paint);
            //画基线
            paint.setColor(Color.GREEN);
            canvas.drawLine(baseLineX, baseLineY, 2000, baseLineY, paint);
            //画descent
            paint.setColor(Color.CYAN);
            canvas.drawLine(baseLineX, descent, 2000, descent, paint);
            //画bottom
            paint.setColor(Color.BLUE);
            canvas.drawLine(baseLineX, bottom, 2000, bottom, paint);
    
    
    5条线

    三、所绘文字宽高和占用矩形区域获取

    1.高度
    int height = fontMetrics.bottom - fontMetrics.top;//所占高度
    
    2.宽度
    int width = paint.measureText(String text);
    
    3.文字显示最小矩形
    public void getTextBounds(String text, int start, int end, Rect bounds);
    public void getTextBounds(char[] text, int index, int count, Rect bounds);
    

    注意:这里获得的bounds获取的y轴是以基线的相对位置的值,所以我们获取的bounds顶部和底部需要加上基线的高度,才是准确位置
    例如:

            int baseLineY = 800;
            int baseLineX = 0 ;
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(Color.BLACK);
            paint.setAntiAlias(true);
            paint.setTextSize(300); //以px为单位
            paint.setStrokeWidth(3);
            String text = "S C g j";
            canvas.drawText(text, baseLineX, baseLineY, paint);
    
            //获取最小区域值,注意这里获取的是对应基线的比较高度,所以top和bottom需要加上基线高度
            Rect minRect = new Rect();
            paint.getTextBounds(text,0,text.length(),minRect);
            int left = minRect.left;
            int top = baseLineY+minRect.top;
            int right = minRect.right;
            int bottom = baseLineY+minRect.bottom;
    
            paint.setColor(Color.GREEN);
            canvas.drawLine(0,baseLineY,2000,baseLineY,paint);//基线
            canvas.drawLine(left,0,left,2000,paint);//9
            canvas.drawLine(0,top,2000,top,paint);//基线+( -221)
            canvas.drawLine(right,0,right,2000,paint);//815
            canvas.drawLine(0,bottom,2000,bottom,paint);//基线 +66
    
            L.e(minRect.toShortString());// [9,-221][815,66]
            paint.setColor(Color.RED);
            canvas.drawRect(new RectF(left,top,right,bottom),paint);
    
    我们分别找到这四个点[9,-221][815,66]对应的关系
    4.文字占用空间矩形
            int baseLineY = 800;
            int baseLineX = 0 ;
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(Color.BLACK);
            paint.setAntiAlias(true);
            paint.setTextSize(300); //以px为单位
            paint.setStrokeWidth(3);
            String text = "S C g j";
            canvas.drawText(text, baseLineX, baseLineY, paint);
    
            //获取最小区域值,注意这里获取的是对应基线的比较高度,所以top和bottom需要加上基线高度
            Rect minRect = new Rect();
            paint.getTextBounds(text,0,text.length(),minRect);
            int left = minRect.left;
            int top = baseLineY+minRect.top;
            int right = minRect.right;
            int bottom = baseLineY+minRect.bottom;
    
            L.e(minRect.toShortString());// [9,-221][815,66]
            paint.setColor(Color.RED);
            canvas.drawRect(new RectF(left,top,right,bottom),paint);
    
            //画text所占的区域
            Paint.FontMetricsInt fm = paint.getFontMetricsInt();
            int spaceTop = baseLineY + fm.top;
            int spaceBottom = baseLineY + fm.bottom;
            int width = (int)paint.measureText(text);
            Rect rect = new Rect(baseLineX,spaceTop,baseLineX+width,spaceBottom);
            paint.setColor(Color.GREEN);
            canvas.drawRect(rect,paint);
    
    占用空间和显示区域

    相关文章

      网友评论

        本文标题:画布的drawText()

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