问题一:在自定义控件绘制文字的时候怎么确定文字的宽度(不是view的宽度),或者其中几个字符的宽度?
下面有两个方法,可以测量指定几个字符的宽度。
/**
* @param text 测量的String
* @return 返回测量宽度结果
*/
public float measureText(String text) {}
/**
* @param text 要测量的字符串
* @param start 起始测量索引
* @param end 要测量字符结束索引
* @return 返回测量宽度
*/
public float measureText(CharSequence text, int start, int end)
了解canvas.drawtext方法是要先指定基准线的位置,不然绘制会出现字体不显示的问题。如下图所示:
最后按照这个位置问题,下了下面的代码:
public MyTestTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化画五线谱paint
linePaint = new Paint();
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setColor(Color.RED);
linePaint.setStrokeWidth(3.0f);
//初始化写字的Paint
textPaint = new Paint();
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(300);
//设置文字的旋转角度,官方推荐-0.25
//textPaint.setTextSkewX(-0.25f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 开始绘制文字
* @param text 要被画的字体
* @param x x坐标,开始绘制
* @param y y坐标,注意是baseline的y值
* @param paint The paint used for the text (e.g. color, size, style)
*/
float ybase = 600.0f;
canvas.drawText("ab思g", 100.0f, ybase, textPaint);
//测量字体的高度
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float top = fontMetrics.top;
float ascent = fontMetrics.ascent;
float descent = fontMetrics.descent;
float leading = fontMetrics.leading;//baseline参考基线
float bottom = fontMetrics.bottom;
//开始绘制残凹陷,
//绘制baseline
Path basePath = generatePath(50, 600);
basePath.lineTo(1020, 600);
canvas.drawPath(basePath, generatePaint(Color.RED));
//bottom
Path bottomPath = generatePath(50, ybase + bottom);
bottomPath.lineTo(1020, ybase + bottom);
canvas.drawPath(bottomPath, linePaint);
//绘制descent
Path descentPath = generatePath(50, ybase + descent);
descentPath.lineTo(1020, ybase + descent);
canvas.drawPath(descentPath, generatePaint(Color.BLUE));
//绘制ascent
float asentY = ybase + ascent;
System.out.println("test 数值 asentY=" + asentY);
Path asentPath = generatePath(50, asentY);
asentPath.lineTo(1020, asentY);
canvas.drawPath(asentPath, generatePaint(Color.DKGRAY));
//绘制top
Path topPath = generatePath(50, ybase + top);
topPath.lineTo(1020, ybase + top);
canvas.drawPath(topPath, generatePaint(Color.GREEN));
//绘制middle
float middleY = ybase-((bottom - top) / 2-bottom);
Path middlePath = generatePath(0, middleY);
middlePath.lineTo(1080,middleY);
canvas.drawPath(middlePath,generatePaint(Color.RED));
}
private Paint generatePaint(int color) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
paint.setStrokeWidth(3.0f);
return paint;
}
private Path generatePath(float moveX, float moveY) {
Path path = new Path();
path.moveTo(moveX, moveY);
return path;
}
最终的结果图如下,有些差别。
总结:1.实践出真知
2.top是负数,bottom’是正数,这说明都是相对于baseline而言,baseline是和leading相等的。
float top = fontMetrics.top;
float ascent = fontMetrics.ascent;
float descent = fontMetrics.descent;
float leading = fontMetrics.leading;//baseline参考基线
float bottom = fontMetrics.bottom;