自定义控件之绘图-drawText()

一、概述

1.基线

canvas在利用drawText绘制文字时,是有规则的,这个规则就是基线,当基线确定时,文字的位置也就确定了
在这里插入图片描述
如图上面红色的线就是基线

2.canvase的drawText()

1.canvas.drawText()与基线

public class CircleView extends View {
    public CircleView(Context context){
        super(context);
    }
    public CircleView(Context context, AttributeSet attr) {
        super(context,attr);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";
       
        Paint paint = new Paint();
        paint.setStrokeWidth(7);
        paint.setColor(Color.RED);
        paint.setTextSize(200);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);

        canvas.drawLine(baseLineX,baseLineY,3000,baseLineY,paint);

        paint.setColor(Color.GREEN);
        canvas.drawText(text,baseLineX,baseLineY,paint);//以(0,200)为原点
    }
}

MainActivity中

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:id="@+id/root"
    android:layout_height="fill_parent">

    <com.example.myview.CircleView
        android:id="@+id/circleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

自定义控件之绘图-drawText()_第1张图片
蓝色的点为原点坐标,即传入(x,y)的值。我的理解x的值可想为矩形距左边的位置,y值可想为矩形距离顶部的位置

  • 当x坐标,基线位置,文字大小确定以后,文字的位置也就确定了

2.paint.setTextAlign(Paint.Align.XXX)

  • 原点坐标中的x代表所要绘制文字所在矩形的相对位置。相对位置就是指指定点(x,y)在在所要绘制矩形的位置。我们知道所绘制矩形的纵坐标是由Y值来确定的,而相对x坐标的位置,只有左、中、右三个位置了。也就是所绘制矩形可能是在x坐标的左侧绘制,也有可能在x坐标的中间,也有可能在x坐标的右侧

paint.setTextAlign(Paint.Align.LEFT)

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";

        Paint paint = new Paint();
        paint.setTextSize(200);
        paint.setStrokeWidth(7);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);


       canvas.drawLine(baseLineX,baseLineY,3000,baseLineY,paint);


        paint.setColor(Color.GREEN);
        paint.setTextAlign(Paint.Align.LEFT);//原点(x,y)在矩形的左侧,矩形从(x,y)的点开始绘制
        canvas.drawText(text,baseLineX,baseLineY,paint);
    }

自定义控件之绘图-drawText()_第2张图片

paint.setTextAlign(Paint.Align.CENTER);

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";

        Paint paint = new Paint();
        paint.setTextSize(200);
        paint.setStrokeWidth(7);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);


        canvas.drawLine(baseLineX,baseLineY,3000,baseLineY,paint);


        paint.setColor(Color.GREEN);
        paint.setTextAlign(Paint.Align.CENTER);//原点(x,y)在矩形的中间,系统会根据(x,y)的位置和文字所在矩形大小,会计算出当前开始绘制的点,使得原点(x,y)正好在所要绘制的矩形的正中间。
        canvas.drawText(text,baseLineX,baseLineY,paint);
    }

自定义控件之绘图-drawText()_第3张图片

paint.setTextAlign(Paint.Align.RIGHT);

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";

        Paint paint = new Paint();
        paint.setTextSize(200);
        paint.setStrokeWidth(7);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);

        canvas.drawLine(baseLineX,baseLineY,3000,baseLineY,paint);


        paint.setColor(Color.GREEN);
        paint.setTextAlign(Paint.Align.RIGHT);//原点(x,y)在矩形的右侧,相当于矩形的结束位置为(x,y)
        canvas.drawText(text,baseLineX,baseLineY,paint);
    }

在这里插入图片描述

3.FontMetrics

自定义控件之绘图-drawText()_第4张图片
除了基线以外,如图所示(上图中bottom和descent并不是同一条线,图中两条线挨的比较近),另外还有四条线,分别是ascent,descent,top,bottom,他们的意义分别是:

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

(1)利用FontMetrics中的方法得到四条线

 		Paint.FontMetrics fontMetrics = paint.getFontMetrics();//获取FontMetrics对象
        float ascent = fontMetrics.ascent + baseLineY;
        float top = fontMetrics.top + baseLineY;
        float descent = fontMetrics.descent + baseLineY;
        float bottom =  fontMetrics.bottom + baseLineY;

FontMetrics中的ascent,descent,top,bottom这个变量的值用来计算这四条条线的位置,并不等价于画出来的四条线,可以自己先画出四条FontMetrics中的ascent,descent,top,bottom这个变量的值,再画出所要的ascent,descent,top,bottom,可看出差别

(2)获取FontMetrics对象
Paint paint = new Paint();
Paint.FontMetrics fm = paint.getFontMetrics();
Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();

通过paint.getFontMetrics()得到对应的FontMetrics对象。这里还有另外一个FontMetrics同样的类叫做FontMetricsInt,它的意义与FontMetrics完全相同,只是得到的值的类型不一样而已,FontMetricsInt中的四个成员变量的值都是Int类型,而FontMetrics得到的四个成员变量的值则都是float类型的。

(3)代码实现
public class CircleView extends View {
    public CircleView(Context context){
        super(context);
    }
    public CircleView(Context context, AttributeSet attr) {
        super(context,attr);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";

        Paint paint = new Paint();
        paint.setTextSize(120);
        paint.setStrokeWidth(3);
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float ascent = fontMetrics.ascent + baseLineY;
        float top = fontMetrics.top + baseLineY ;
        float descent = fontMetrics.descent + baseLineY;
        float bottom =  fontMetrics.bottom  + baseLineY;


        paint.setColor(Color.GREEN);
        canvas.drawLine(baseLineX,baseLineY,3000,baseLineY,paint);

        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX,ascent,3000,ascent,paint);

        paint.setColor(Color.BLUE);
        canvas.drawLine(baseLineX,top,3000,top,paint);

        paint.setColor(Color.RED);
        canvas.drawLine(baseLineX,descent,3000,descent,paint);

        paint.setColor(Color.BLUE);
        canvas.drawLine(baseLineX,bottom,3000,bottom,paint);

        paint.setColor(Color.GREEN);
        canvas.drawText(text,baseLineX,baseLineY,paint);
    }
}

二、所绘文字宽度、高度和最小矩形获取

1.获取文字宽度和高度

        float height = bottom - top;//高度
        float width = paint.measureText(text);//宽度

2绘制最小矩形与最大矩形

paint.getTextBounds()得到最小矩形

Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
Log.i("Test",minRect.toShortString());

打印粗来的左上角的Y坐标是个负数,因为我们没有给getTextBounds()传递基线位置。那它就是以(0,0)为基线来得到这个最小矩形的!所以这个最小矩形的位置就是以(0,0)为基线的结果。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int baseLineX = 0;
        int baseLineY = 200;
        String text = "Hello World";

        Paint paint = new Paint();
        paint.setTextSize(120);
        paint.setStrokeWidth(3);
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        int top = (int) (fontMetrics.top + baseLineY);
        int bottom = (int) (fontMetrics.bottom  + baseLineY);
        int width = (int) paint.measureText(text);

        paint.setColor(Color.GREEN);
        Rect rect = new Rect(baseLineX,top,width,bottom);
        canvas.drawRect(rect,paint);

        paint.setColor(Color.RED);
        Rect minRect = new Rect();
        paint.getTextBounds(text,0,text.length(),minRect);
        minRect.top = minRect.top + baseLineY;
        minRect.bottom = minRect.bottom + baseLineY;
        canvas.drawRect(minRect,paint);

        paint.setColor(Color.BLACK);
        canvas.drawText(text,baseLineX,baseLineY,paint);
    }

在这里插入图片描述

你可能感兴趣的:(自定义控件之绘图-drawText())