2011-01-05 10 views
4

キャンバスを使用して、指定された四角形に収まる短いラベルテキスト(1-2文字)を描画します。 私が使用するスケーリングは、このrecangleのサイズが小さくなるようなものです。つまり、約1です。指定された矩形内にテキストを描画する

私が直面している問題は、最適な(Canva.drawText()を使用して)テキストを描画する前に、Paint.setTextSizeで使用するテキストサイズを調整します。 私は​​オブジェクトを使用して、一般的なフォントの寸法を浮動小数点として取得するか、getTextBounds(String text, int start, int end, Rect bounds)を使用して、テキストの境界ボックスを整数矩形として取得することができます。私が使用するスケーリングのために、後者の整数バウンディングボックスは、私の目的に合った最適なテキストサイズを計算するために不正確になります。

高精度のテキストのバウンディングボックスを取得する方法がありますが(getStringBounds(String str, Graphics context)java.awt.FontMetricsなど)、適切な方法が見つかりませんでした。

答えて

1

私はちょうど数日前にそれをしました:See my blog

あなたはStaticLayoutを使用します。

// bmp1 is a source bitmap (in that case 44x44px big). 
// density is the screen density, you will need to retrieve it yourself as well. 

canvas.drawBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.overlay_44x44), new Matrix(), null); 

// Initialize using a simple Paint object. 
final TextPaint tp = new TextPaint(WHITE); 

// Save the canvas state, it might be re-used later. 
canvas.save(); 

// Create a padding to the left & top. 
canvas.translate(4*density, 4*density); 

// Clip the bitmap now. 
canvas.clipRect(new Rect(0, 0, bmp1.getWidth(),(int) (bmp1.getHeight() - (6*density)))); 

// Basic StaticLayout with mostly default values 
StaticLayout sl = new StaticLayout(message, tp, bmp1.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); 
sl.draw(canvas); 

// Restore canvas. 
canvas.restore(); 
+0

申し訳ありませんが、私のオリジナルの質問はあまり正確ではありませんでした。問題は、テキストのレイアウトではなく(テキストの長さは1〜2文字です)、最適なテキストサイズを計算することです。 –

7

私は今もこの問題で忙しかったです。

残念ながら私はネイティブソースをまだインストールしていませんでしたが、実際のテキスト出力(特に小さなフォントサイズの場合はテキスト測定(getTextBounds()とmeasureText Moritz' screenshotに見られるように)。 私は、測定方法がcharのfloat幅を使用し、実際のテキスト出力がint(おそらくパフォーマンスのため)を使用すると仮定します。絶対に正確なサイズが必要な場合(例えば、自動サイズ調整の場合)、これはもちろん失敗します。 モノスペースフォントで少し実験しました。この画像では、これらの実験の一部を示します。

Android Autoscale experiments

これらの実験のテキストスケールは自動スケーリングによって設定されました。

一番上の行では、整数の増分でボックスを作成しました。これらはアンドロイドのテキスト出力と一致します。あなたは、最後の暗号は画面に一致しないことがわかります!

2番目の行では、ボックスは浮動小数点数で作成されました。ボックスは画面によくマッチしますが、アンドロイドのテキスト出力と一致しません!

最後の行では、ボックスは浮動インクリメントでインクリメントされ、テキストは同じ増分だけcharによってcharで出力されました。ボックスと文字の両方が完璧にフィットします。

私の結論として、Androidのテキスト出力を正確な幅に設定することは現在できません。この問題は、正確な測定方法ではないようです。問題は、setTextSize()で正確なテキスト幅を設定できないということです。

はこれを再現するために、次の試してみてください。

5月26日12時18分18秒:

float width = 100; // define a width which should be achieved 
    m_textPaint.setTextSize(100); // set a text size surely big enough 
    Rect r = new Rect(); 
    String s = new String("This is a test text"); 
    m_textPaint.getTextBounds(s, 0, s.length(), r); // measure the text with a random size 
    float fac = width/r.width(); // compute the factor, which will scale the text to our target width 
    Log.i("MyTestOutput", "current text width:" + r.width()); 
    Log.i("MyTestOutput", "wanted text width:" + width); 
    Log.i("MyTestOutput", "factor:" + fac); 
    Log.i("MyTestOutput", "expected result:" + (float) r.width() * fac); 
    m_textPaint.setTextSize(m_textPaint.getTextSize() * fac); 
    m_textPaint.getTextBounds(s, 0, s.length(), r); // now final measurement: whats the real width? 
    Log.i("MyTestOutput", "real result:" + r.width()); 

私はの出力を取得します。420:I/MyTestOutput(23607):現在のテキスト幅:1125

5月26日12:18:18.425:I/MyTestOutput(23607):テキスト幅を望ん:100.0

5月26日12:18: 18.425:I/MyTestOutput(23607):因子:0.08888889

5月26日12:18:18.425:I/MyTestOutput(23607):期待される結果:100.0

5月26日12:18:18.430:I/MyTestOutput(23607):実際の結果:94

私の意見では、自動スケーリングされたテキストを非常に正確に達成する方法は、 です。a)テキストサイズを測定して設定することによって自動スケールします。 b)charを自己計算インクリメントで出力します。

残念ながら、これはモノスペースフォントでのみ機能します。他のフォントについては、もっと複雑になりますが、可能です。

関連する問題