2011-10-10 16 views
7

Zmagałem się z pomiarem tekstu i przeskalowanymi płótnami.pomiar tekstu na skalowanym płótnie

Gdy płótno nie jest przeskalowane, getTextBounds i measureText zapewniają dokładne wyniki. Jednak, gdy płótno jest skalowane, obie metody nie dostarczają wyników, które pasują do rzeczywistego rozmiaru drukowanego tekstu.

Do testowania Utworzyłem podklasę Widok z następującym sposobem 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); 

do skalowania = 0.5 pojawia się następujący komunikat: canvas scaling 0.5

do skalowania = 0,51 następujący wynik pokazano: canvas scaling 0.51

Żółta ramka oznacza linię prostą dostarczoną z getTextBounds, przerywana cyjan rect jest renderowana przy użyciu szerokości dostarczonej przez fr om measureText.

Jak widać, tekst ze skalowaniem = 0,5 jest mniejszy niż zmierzone wymiary, a przy skalowaniu = 0,51 narysowany tekst jest znacznie większy niż wymiar mierzony.

Każda pomoc jest doceniana!

Odpowiedz

4

Ok, właśnie dowiedziałeś się, jak obejść problem.

Problem polega na tym, że Paint nie wie o skalowaniu Canvas. Dlatego measureText i getTextBounds dostarczają wynik nieskalowany. Ponieważ jednak rozmiar czcionki nie jest skalowany liniowo (jednak narysowany rect nie), należy nadrobić ten efekt ręcznie.

Zatem rozwiązaniem byłoby:

// 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

Korzystanie Mono for Android musiałem użyć wyświetlacza metryki, jak pokazano tutaj:

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); 
} 

Gdzie f.DrawingFont jest Androdid.Text.TextPaint GetDisplay jest:

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

I ta sama metoda w Javie jest:

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

ty jesteś korekcja jest stosowana zawsze i nie rekompensuje wartości skalowania w płótnie, nie? Właściwie nie uważam, że obliczenie prostokąta ograniczającego jest niepoprawne, ale kod renderujący czcionki nie wybiera właściwego rozmiaru czcionki zgodnie ze skalowaniem płótna ... –

+0

Tak, jest obliczane zawsze, że wymiary tekstu są potrzebne bez skalowania płótno. –

+0

Zapominając o tym, jest używana głównie do pozycjonowania tekstu na płótnie, znając dokładne wymiary i pozycję. –