2011-02-05 75 views
41

目標:純粹Canvas上的Android> = 1.6。如何垂直排列文本?

假設我想寫一個函數,它將繪製一個(寬度,高度)大的紅色矩形,然後在裏面繪製一個黑色的文本。我希望文字在矩形的中心可視化。所以讓我們嘗試:

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;

似乎工作或多或少好,但必須有更好的方法。

+18

每次您在問題標題中放入* Android *時,小貓都會死亡,請不要這樣做。謝謝。 – 2011-02-05 20:20:57

回答

83

實例來集中在cxcy

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

這些將僅產生相同的結果時top0。對於所有尺寸的某些字體或某些尺寸的其他字體,情況可能如此,但不適用於所有尺寸的所有字體。

9

使用mPaint.getTextBounds()您可以詢問繪製時文本的大小,然後使用該信息可以計算出要繪製的文本的位置。

+2

getTextBounds()屬於Paint而不是Canvas – Melllvar 2011-06-12 00:59:04

+4

請記住,當您說垂直居中的文本時,您可能意味着圍繞字符的上升部分,而不是基線。當您使用Align.CENTER繪圖時,Y座標將以字符基線爲中心。 – 2012-04-22 18:38:13

+0

@CameronLowellPalmer你能詳細解釋一下嗎? – Peterdk 2013-06-15 19:31:11

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); 
} 
24
textY = topLeftY + height/2 - (mPaint.descent() + mPaint.ascent())/2 

從 「基準」 的距離 「中心」 應該是-(mPaint.descent() + mPaint.ascent())/2

5
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); 
13

由於在Y處繪製文本意味着文本的基線將結束Ÿ像素向下從原點,你需要的時候你要(width, height)尺寸的矩形內文本居中做的是:

paint.setTextAlign(Paint.Align.CENTER); // centers horizontally 
canvas.drawText(text, width/2, (height - paint.ascent())/2, paint); 

請記住,上升是負的(這解釋了負號)。

這不考慮下降,這通常是你想要的(上升通常是高於基線的高度)。