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>
蓝色的点为原点坐标,即传入(x,y)的值。我的理解x的值可想为矩形距左边的位置,y值可想为矩形距离顶部的位置
@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);
}
@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);
}
@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);
}
除了基线以外,如图所示(上图中bottom和descent并不是同一条线,图中两条线挨的比较近),另外还有四条线,分别是ascent,descent,top,bottom,他们的意义分别是:
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,可看出差别
Paint paint = new Paint();
Paint.FontMetrics fm = paint.getFontMetrics();
Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();
通过paint.getFontMetrics()得到对应的FontMetrics对象。这里还有另外一个FontMetrics同样的类叫做FontMetricsInt,它的意义与FontMetrics完全相同,只是得到的值的类型不一样而已,FontMetricsInt中的四个成员变量的值都是Int类型,而FontMetrics得到的四个成员变量的值则都是float类型的。
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);
}
}
float height = bottom - top;//高度
float width = paint.measureText(text);//宽度
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);
}