2011-10-10 45 views
7

我一直在努力處理文字測量和縮放畫布。在縮放畫布上測量文字

當畫布未縮放時,getTextBounds和measureText會提供準確的結果。但是,當縮放畫布時,兩種方法都不會提供與打印文本的實際大小相匹配的結果。

爲了測試我創建視圖的子類用下面的onDraw方法:

final float scaling = 0.51f; 
final int fontSize = 50; 

canvas.scale(scaling, scaling); 
font = Typeface.create("Arial", Typeface.NORMAL); 

Paint paint = new Paint(); 
paint.setColor(0xff4444ff); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
paint.setAntiAlias(true); 

int x = 10; 
int y = 100; 
final String text = "Lorem ipsum dolor sit amet, consectetur adipisici elit..."; 
canvas.drawText(text, x, y, paint); 

// draw border using getTextBounds 

paint.setColor(0xffff0000); 
paint.setStyle(Paint.Style.STROKE); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
Rect bounds = new Rect(); 
paint.getTextBounds(text, 0, text.length(), bounds); 
bounds.offset(x, y); 
paint.setColor(0x80ffff00); 
canvas.drawRect(bounds, paint); 

// draw border using measureText 

float w = paint.measureText(text); 
bounds.left = x; 
bounds.right = (int) Math.ceil(bounds.left + w); 
bounds.top -= 10; 
bounds.bottom += 10; 
paint.setColor(0x8000ffff); 
paint.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 0)); 
canvas.drawRect(bounds, paint); 

用於縮放= 0.5我得到以下輸出: canvas scaling 0.5

用於縮放= 0.51以下結果顯示爲: canvas scaling 0.51

黃色實心邊框標記從getTextBounds傳遞的矩形,虛線的青色矩形使用寬度傳遞的fr om measureText。

正如您所看到的,縮放比例= 0.5的文本小於測量的尺寸,縮放比例= 0.51,繪製的文本比測量的尺寸大得多。

任何幫助表示讚賞!

回答

4

好的,只是發現如何繞過這個問題。

問題是,畫圖不知道畫布縮放。因此,measureText和getTextBounds將傳遞未縮放的結果。但是,由於字體大小不會線性縮放(但是,繪製的矩形可以),所以您必須手動彌補該效果。

因此,解決辦法是:

// paint the text as usual 
Paint paint = new Paint(); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
canvas.drawText(text, x, y, paint); 


// measure the text using scaled font size and correct the scaled value afterwards 
Paint paint = new Paint(); 
paint.setTypeface(font); 
paint.setTextSize(fontSize * scaling); 
float w = paint.measureText(text)/scaling; 
0

使用Mono for Android我不得不使用顯示器的指標如下所示:

public override System.Drawing.SizeF MeasureString(MyFont f, string text) 
{ 
    Rect r = new Rect(); 

    f.DrawingFont.GetTextBounds(text, 0, text.Length, r); 

    //Manual scaling using DisplayMetrics due to Android 
    //issues for compatibility with older versions 
    Android.Util.DisplayMetrics metrics = new Android.Util.DisplayMetrics(); 
    GetDisplay.GetMetrics(metrics); 

    return new System.Drawing.SizeF(r.Width(), r.Height() * metrics.Density); 
} 

f.DrawingFontAndrodid.Text.TextPaint GetDisplay是:

private Display GetDisplay() 
{ 
    return this.GetSystemService(Android.Content.Context.WindowService).JavaCast<Android.Views.IWindowManager>().DefaultDisplay; 
} 

而且在Java中,同樣的方法是:

private Display getDisplay() { 
    return ((WindowManager) getContext().getSystemService(
      Context.WINDOW_SERVICE)).getDefaultDisplay(); 
} 
+0

你改正一直應用,並且不補償畫布縮放值,不是嗎?實際上我並不認爲邊界矩的計算是不正確的,但是字體渲染代碼根據畫布縮放比例沒有選擇適當的字體大小...... –

+0

是的,總是計算出不需要縮放就需要文本尺寸畫布。 –

+0

忘了提及這個主要用於在畫布中定位文字,知道確切的尺寸和位置是必要的。 –