我试图使用下面的代码显示一个文本。
问题是文本没有水平居中。
当我为drawText设置坐标时,它将文本的底部设置在这个位置。我想要的文本被绘制,使文本也是水平居中。
这是一张进一步展示我的问题的图片:
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//canvas.drawRGB(2, 2, 200);
Paint textPaint = new Paint();
textPaint.setARGB(200, 254, 0, 0);
textPaint.setTextAlign(Align.CENTER);
textPaint.setTypeface(font);
textPaint.setTextSize(300);
canvas.drawText("Hello", canvas.getWidth()/2, canvas.getHeight()/2 , textPaint);
}
垂直对齐是困难的,因为文本下降和上升发生了,很多人使用Paint.getTextBounds()来检索TextWidth和TextHeight,但它不会使文本非常中心。这里我们可以使用Paint.measureText()来计算TextWidth, TextHeight我们简单地用下降和上升做减法,然后我们得到了最接近的TextSize,下面的工作对彼此来说都是相当容易的。
// the Paint instance(should be assign as a field of class).
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(getResources().getDimension(R.dimen.btn_textsize));
// the display area.
Rect areaRect = new Rect(0, 0, 240, 60);
// draw the background style (pure color or image)
mPaint.setColor(Color.BLACK);
yourCanvas.drawRect(areaRect, mPaint);
String pageTitle = "文字小说";
RectF bounds = new RectF(areaRect);
// measure text width
bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
// measure text height
bounds.bottom = mPaint.descent() - mPaint.ascent();
bounds.left += (areaRect.width() - bounds.right) / 2.0f;
bounds.top += (areaRect.height() - bounds.bottom) / 2.0f;
mPaint.setColor(Color.WHITE);
yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);
顺便说一下,我们强烈建议使用RectF而不是Rect,因为位置需要更准确的值,在我的经验,RectF做的顶部和底部偏差只有一个像素在xhdpi设备,Rect将是两个以上。
垂直对齐是困难的,因为文本下降和上升发生了,很多人使用Paint.getTextBounds()来检索TextWidth和TextHeight,但它不会使文本非常中心。这里我们可以使用Paint.measureText()来计算TextWidth, TextHeight我们简单地用下降和上升做减法,然后我们得到了最接近的TextSize,下面的工作对彼此来说都是相当容易的。
// the Paint instance(should be assign as a field of class).
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(getResources().getDimension(R.dimen.btn_textsize));
// the display area.
Rect areaRect = new Rect(0, 0, 240, 60);
// draw the background style (pure color or image)
mPaint.setColor(Color.BLACK);
yourCanvas.drawRect(areaRect, mPaint);
String pageTitle = "文字小说";
RectF bounds = new RectF(areaRect);
// measure text width
bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
// measure text height
bounds.bottom = mPaint.descent() - mPaint.ascent();
bounds.left += (areaRect.width() - bounds.right) / 2.0f;
bounds.top += (areaRect.height() - bounds.bottom) / 2.0f;
mPaint.setColor(Color.WHITE);
yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);
顺便说一下,我们强烈建议使用RectF而不是Rect,因为位置需要更准确的值,在我的经验,RectF做的顶部和底部偏差只有一个像素在xhdpi设备,Rect将是两个以上。
我创建了一个方法来简化它:
public static void drawCenterText(String text, RectF rectF, Canvas canvas, Paint paint) {
Paint.Align align = paint.getTextAlign();
float x;
float y;
//x
if (align == Paint.Align.LEFT) {
x = rectF.centerX() - paint.measureText(text) / 2;
} else if (align == Paint.Align.CENTER) {
x = rectF.centerX();
} else {
x = rectF.centerX() + paint.measureText(text) / 2;
}
//y
metrics = paint.getFontMetrics();
float acent = Math.abs(metrics.ascent);
float descent = Math.abs(metrics.descent);
y = rectF.centerY() + (acent - descent) / 2f;
canvas.drawText(text, x, y, paint);
Log.e("ghui", "top:" + metrics.top + ",ascent:" + metrics.ascent
+ ",dscent:" + metrics.descent + ",leading:" + metrics.leading + ",bottom" + metrics.bottom);
}
rectF是你想要绘制文本的区域,就是这样。
细节