目标:纯画布上的Android> = 1.6。
假设我想编写一个绘制(宽度,高度)大红色矩形的函数,然后在里面绘制一个黑色 Hello World 文本。我希望文本在视觉上位于矩形的中心。所以让我们试试:
void drawHelloRectangle(Canvas c, int topLeftX,
int topLeftY, int width, int height) {
Paint mPaint = new Paint();
// height of 'Hello World'; height*0.7 looks good
int fontHeight = (int)(height*0.7);
mPaint.setColor(COLOR_RED);
mPaint.setStyle(Style.FILL);
c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint);
mPaint.setTextSize(fontHeight);
mPaint.setColor(COLOR_BLACK);
mPaint.setTextAlign(Align.CENTER);
c.drawText( "Hello World", topLeftX+width/2, ????, mPaint);
}
现在我不知道在????
标记的drawText参数中放什么,即我不知道如何垂直对齐文本。
像
这样的东西???? = topLeftY + height / 2 + fontHeight / 2 - fontHeight / 8;
似乎或多或少有效,但必须有更好的方法。
答案 0 :(得分:99)
cx
和cy
为中心的示例:private final Rect textBounds = new Rect(); //don't new this up in a draw method
public void drawTextCentred(Canvas canvas, Paint paint, String text, float cx, float cy){
paint.getTextBounds(text, 0, text.length(), textBounds);
canvas.drawText(text, cx - textBounds.exactCenterX(), cy - textBounds.exactCenterY(), paint);
}
height()/2f
不能正常工作? exactCentre()
= (top + bottom) / 2f
。
height()/2f
= (bottom - top) / 2f
当top
为0
时,这些结果只会产生相同的结果。对于某些尺寸的某些字体或某些尺寸的其他字体,可能会出现这种情况,但不适用于所有尺寸的所有字体。
答案 1 :(得分:25)
textY = topLeftY + height/2 - (mPaint.descent() + mPaint.ascent()) / 2
从“基线”到“中心”的距离应为-(mPaint.descent() + mPaint.ascent()) / 2
答案 2 :(得分:21)
根据steelbytes的回复,更新后的代码如下所示:
void drawHelloRectangle(Canvas c, int topLeftX, int topLeftY, int width, int height) {
Paint mPaint = new Paint();
// height of 'Hello World'; height*0.7 looks good
int fontHeight = (int)(height*0.7);
mPaint.setColor(COLOR_RED);
mPaint.setStyle(Style.FILL);
c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint);
mPaint.setTextSize(fontHeight);
mPaint.setColor(COLOR_BLACK);
mPaint.setTextAlign(Align.CENTER);
String textToDraw = new String("Hello World");
Rect bounds = new Rect();
mPaint.getTextBounds(textToDraw, 0, textToDraw.length(), bounds);
c.drawText(textToDraw, topLeftX+width/2, topLeftY+height/2+(bounds.bottom-bounds.top)/2, mPaint);
}
答案 3 :(得分:15)
由于在Y处绘制文本意味着文本的基线将从原点开始向下Y像素,因此当您希望将文本置于{{1的矩形中心时,需要执行的操作维度是:
(width, height)
请记住,上升是负数(这解释了减号)。
这不考虑下降,这通常是你想要的(上升通常是高于基线的上限的高度)。
答案 4 :(得分:9)
使用mPaint.getTextBounds(),您可以询问绘制时文本的大小,然后使用该信息计算您想要绘制的文本。
答案 5 :(得分:7)
public static PointF getTextCenterToDraw(String text, RectF region, Paint paint) {
Rect textBounds = new Rect();
paint.getTextBounds(text, 0, text.length(), textBounds);
float x = region.centerX() - textBounds.width() * 0.4f;
float y = region.centerY() + textBounds.height() * 0.4f;
return new PointF(x, y);
}
用法:
PointF p = getTextCenterToDraw(text, rect, paint);
canvas.drawText(text, p.x, p.y, paint);
答案 6 :(得分:1)
在试图解决我的问题时我偶然发现了这个问题,@ Weston的答案对我来说很好。
对于Kotlin:
private fun drawText(canvas: Canvas) {
paint.textSize = 80f
val text = "Hello!"
val textBounds = Rect()
paint.getTextBounds(text, 0, text.length, textBounds);
canvas.drawText(text, cx- textBounds.exactCenterX(), cy - textBounds.exactCenterY(), paint);
//in case of another Rect as a container:
//canvas.drawText(text, containerRect.exactCenterX()- textBounds.exactCenterX(), containerRect.exactCenterY() - textBounds.exactCenterY(), paint);
}
答案 7 :(得分:0)
这是SkiaSharp C#扩展方法,适用于任何寻求它的人
public static void DrawTextCenteredVertically(this SKCanvas canvas, string text, SKPaint paint, SKPoint point)
{
var textY = point.Y + (((-paint.FontMetrics.Ascent + paint.FontMetrics.Descent) / 2) - paint.FontMetrics.Descent);
canvas.DrawText(text, point.X, textY, paint);
}
答案 8 :(得分:0)
private final Rect textBounds = new Rect();//No need o create again
public void drawTextCentred(Canvas canvas, Paint paint, String text, float cx, float cy, float desiredWidth) {
final float testTextSize = 48f;
paint.setTextSize(testTextSize);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
float desiredTextSize = testTextSize * desiredWidth / bounds.width();
paint.setTextSize(desiredTextSize);
paint.getTextBounds(text, 0, text.length(), textBounds);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, cx, cy - textBounds.exactCenterY(), paint);
}