うまくいけば簡単な質問ですが、例を見つけることができないようです...カスタムView
にCanvas
を介して、そしてonDraw()
に複数行のテキストを書きたいです:
...
String text = "This is\nmulti-line\ntext";
canvas.drawText(text, 100, 100, mTextPaint);
...
私はこれが改行になることを望んでいましたが、その代わりに、\n
がある不可解な文字を見ています。
すべてのポインタが高く評価されています。
ポール
残念ながらAndroidは\n
が何であるかを知りません。あなたがしなければならないのは、\n
を取り除き、Yをオフセットして次の行にテキストを取得することです。このようなもの:
canvas.drawText("This is", 100, 100, mTextPaint);
canvas.drawText("multi-line", 100, 150, mTextPaint);
canvas.drawText("text", 100, 200, mTextPaint);
静的レイアウトを使用する別の方法を見つけました。コードは誰でも参照できるようにここにあります:
TextPaint mTextPaint=new TextPaint();
StaticLayout mTextLayout = new StaticLayout(mText, mTextPaint, canvas.getWidth(), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.save();
// calculate x and y position where your text will be placed
textX = ...
textY = ...
canvas.translate(textX, textY);
mTextLayout.draw(canvas);
canvas.restore();
各行を繰り返します:
int x = 100, y = 100;
for (String line: text.split("\n")) {
canvas.drawText(line, x, y, mTextPaint);
y += mTextPaint.descent() - mTextPaint.ascent();
}
完全な例を書いた
colors.xml
<color name="transparentBlack">#64000000</color>
Javaクラス
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.amit);
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(drawTextToBitmap(this, bm, "Name: Kolala\nDate: Dec 23 2016 12:47 PM, \nLocation: 440 Banquets & Restaurents"));
}
public Bitmap drawTextToBitmap(Context gContext,
Bitmap bitmap,
String gText) {
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Android.graphics.Bitmap.Config bitmapConfig =
bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = Android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
Paint.setColor(Color.WHITE);
// text size in pixels
Paint.setTextSize((int) (25 * scale));
// text shadow
Paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// draw text to the Canvas center
Rect bounds = new Rect();
int noOfLines = 0;
for (String line: gText.split("\n")) {
noOfLines++;
}
Paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = 20;
int y = (bitmap.getHeight() - bounds.height()*noOfLines);
Paint mPaint = new Paint();
mPaint.setColor(getResources().getColor(R.color.transparentBlack));
int left = 0;
int top = (bitmap.getHeight() - bounds.height()*(noOfLines+1));
int right = bitmap.getWidth();
int bottom = bitmap.getHeight();
canvas.drawRect(left, top, right, bottom, mPaint);
for (String line: gText.split("\n")) {
canvas.drawText(line, x, y, Paint);
y += Paint.descent() - Paint.ascent();
}
return bitmap;
}
}
これは@Daveの答えに基づいた私のソリューションです(ありがとうbtw ;-))
import Android.graphics.Canvas;
import Android.graphics.Paint;
public class mdCanvas
{
private Canvas m_canvas;
public mdCanvas(Canvas canvas)
{
m_canvas = canvas;
}
public void drawMultiline(String str, int x, int y, Paint paint)
{
for (String line: str.split("\n"))
{
m_canvas.drawText(line, x, y, Paint);
y += -Paint.ascent() + Paint.descent();
}
}
}
Canvasを継承しようとしましたが、実際には許可されません。したがって、これは中間クラスです!
ストローク幅も考慮するバージョンをここに追加する必要があります。
void drawMultiLineText(String str, float x, float y, Paint paint, Canvas canvas) {
String[] lines = str.split("\n");
float txtSize = -Paint.ascent() + Paint.descent();
if (Paint.getStyle() == Style.FILL_AND_STROKE || Paint.getStyle() == Style.STROKE){
txtSize += Paint.getStrokeWidth(); //add stroke width to the text size
}
float lineSpace = txtSize * 0.2f; //default line spacing
for (int i = 0; i < lines.length; ++i) {
canvas.drawText(lines[i], x, y + (txtSize + lineSpace) * i, Paint);
}
}
これを試して
Paint paint1 = new Paint();
Paint1.setStyle(Paint.Style.FILL);
Paint1.setAntiAlias(true);
Paint1.setColor(Color.BLACK);
Paint1.setTextSize(15);
TextView tv = new TextView(context);
tv.setTextColor(Color.BLACK);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
llp.setMargins(5, 2, 0, 0); // llp.setMargins(left, top, right, bottom);
tv.setLayoutParams(llp);
tv.setTextSize(10);
String text="this is good to see you , i am the king of the team";
tv.setText(text);
tv.setDrawingCacheEnabled(true);
tv.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
canvas.drawBitmap(tv.getDrawingCache(), 5, 10, Paint1);
tv.setDrawingCacheEnabled(false);
はい。 canvas.getFontSpacing()
を増分として使用します。好奇心から自分で試してみましたが、どのフォントサイズでも動作します。
それは動作します。私はテストしました
public Bitmap drawMultilineTextToBitmap(Context gContext,
int gResId,
String gText) {
// prepare canvas
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);
Android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = Android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialiased Paint
TextPaint Paint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
Paint.setColor(Color.rgb(61, 61, 61));
// text size in pixels
Paint.setTextSize((int) (14 * scale));
// text shadow
Paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// set text width to canvas width minus 16dp padding
int textWidth = canvas.getWidth() - (int) (16 * scale);
// init StaticLayout for text
StaticLayout textLayout = new StaticLayout(
gText, Paint, textWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
// get height of multiline text
int textHeight = textLayout.getHeight();
// get position of text's top left corner
float x = (bitmap.getWidth() - textWidth)/2;
float y = (bitmap.getHeight() - textHeight)/2;
// draw text to the Canvas center
canvas.save();
canvas.translate(x, y);
textLayout.draw(canvas);
canvas.restore();
return bitmap;
}
ソース: http://www.skoumal.net/en/Android-drawing-multiline-text-on-bitmap/
GreenBeeによって提案されたソリューションを再利用し、切り捨てが発生した場合に最後に「...」を使用して、指定された範囲に複数行のテキストを描画する関数を作成しました。
public static void drawMultiLineEllipsizedText(final Canvas _canvas, final TextPaint _textPaint, final float _left,
final float _top, final float _right, final float _bottom, final String _text) {
final float height = _bottom - _top;
final StaticLayout measuringTextLayout = new StaticLayout(_text, _textPaint, (int) Math.abs(_right - _left),
Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
int line = 0;
final int totalLineCount = measuringTextLayout.getLineCount();
for (line = 0; line < totalLineCount; line++) {
final int lineBottom = measuringTextLayout.getLineBottom(line);
if (lineBottom > height) {
break;
}
}
line--;
if (line < 0) {
return;
}
int lineEnd;
try {
lineEnd = measuringTextLayout.getLineEnd(line);
} catch (Throwable t) {
lineEnd = _text.length();
}
String truncatedText = _text.substring(0, Math.max(0, lineEnd));
if (truncatedText.length() < 3) {
return;
}
if (truncatedText.length() < _text.length()) {
truncatedText = truncatedText.substring(0, Math.max(0, truncatedText.length() - 3));
truncatedText += "...";
}
final StaticLayout drawingTextLayout = new StaticLayout(truncatedText, _textPaint, (int) Math.abs(_right
- _left), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
_canvas.save();
_canvas.translate(_left, _top);
drawingTextLayout.draw(_canvas);
_canvas.restore();
}
私はすでに1行をキャンバスに変換していたものを使って作業しましたが、Lumisの答えを取り除いて、これで終わりました。 1.3および1.3fは、フォントのサイズを基準にした行間のパディングを意味します。
public static Bitmap getBitmapFromString(final String text, final String font, int textSize, final int textColor)
{
String lines[] = text.split("\n");
textSize = getRelX(textSize); //a method in my app that adjusts the font size relative to the screen size
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint.setTextSize(textSize);
Paint.setColor(textColor);
Paint.setTextAlign(Paint.Align.LEFT);
Typeface face = Typeface.createFromAsset(GameActivity.getContext().getAssets(),GameActivity.getContext().getString(R.string.font) + font + GameActivity.getContext().getString(R.string.font_ttf));
Paint.setTypeface(face);
float baseline = -Paint.ascent(); // ascent() is negative
int width = (int) (Paint.measureText(text) + 0.5f); // round
int height = (int) (baseline + Paint.descent() + 0.5f);
Bitmap image = Bitmap.createBitmap(width, (int)(height * 1.3 * lines.length), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
for (int i = 0; i < lines.length; ++i)
{
canvas.drawText(lines[i], 0, baseline + textSize * 1.3f * i, Paint);
}
return image;
}
StaticLayoutを使用しないソリューション
//Get post text
String text = post.getText();
//Get weight of space character in px
float spaceWeight = Paint.measureText(" ");
//Start main algorithm of drawing words on canvas
//Split text to words
for (String line : text.split(" ")) {
//If we had empty space just continue
if (line.equals("")) continue;
//Get weight of the line
float lineWeight = Paint.measureText(line);
//If our Word(line) doesn't have any '\n' we do next
if (line.indexOf('\n') == -1) {
//If Word can fit into current line
if (cnv.getWidth() - pxx - defaultMargin >= lineWeight) {
//Draw text
cnv.drawText(line, pxx, pxy, Paint);
//Move start x point to Word weight + space weight
pxx += lineWeight + spaceWeight;
} else {
//If Word can't fit into current line
//Move x point to start
//Move y point to the next line
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
//Draw
cnv.drawText(line, pxx, pxy, Paint);
//Move x point to Word weight + space weight
pxx += lineWeight + spaceWeight;
}
//If line contains '\n'
} else {
//If '\n' is on the start of the line
if (line.indexOf('\n') == 0) {
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
cnv.drawText(line.replaceAll("\n", ""), pxx, pxy, Paint);
pxx += lineWeight + spaceWeight;
} else {
//If '\n' is somewhere in the middle
//and it also can contain few '\n'
//Split line to sublines
String[] subline = line.split("\n");
for (int i = 0; i < subline.length; i++) {
//Get weight of new Word
lineWeight = Paint.measureText(subline[i]);
//If it's empty subline that's mean that we have '\n'
if (subline[i].equals("")) {
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
cnv.drawText(subline[i], pxx, pxy, Paint);
continue;
}
//If we have only one Word
if (subline.length == 1 && i == 0) {
if (cnv.getWidth() - pxx >= lineWeight) {
cnv.drawText(subline[0], pxx, pxy, Paint);
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
} else {
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
cnv.drawText(subline[0], pxx, pxy, Paint);
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
}
continue;
}
//If we have set of words separated with '\n'
//it is the first Word
//Make sure we can put it into current line
if (i == 0) {
if (cnv.getWidth() - pxx >= lineWeight) {
cnv.drawText(subline[0], pxx, pxy, Paint);
pxx = defaultMargin;
} else {
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
cnv.drawText(subline[0], pxx, pxy, Paint);
pxx = defaultMargin;
}
} else {
pxx = defaultMargin;
pxy += Paint.descent() - Paint.ascent();
cnv.drawText(subline[i], pxx, pxy, Paint);
pxx += lineWeight + spaceWeight;
}
}
}
}
}
動的テキストのサイズ変更と間隔を使用した私の例は、私に最適です...
public Bitmap fontTexture(String string, final Context context) {
float text_x = 512;
float text_y = 512;
final float scale = context.getResources().getDisplayMetrics().density;
int mThreshold = (int) (THRESHOLD_DIP * scale + 0.5f);
String[] splited = string.split("\\s+");
double longest = 0;
for(String s:splited){
if (s.length() > longest) {
longest = s.length();
}
}
if(longest > MAX_STRING_LENGTH) {
double ratio = (double) MAX_STRING_LENGTH / longest;
mThreshold = (int) ((THRESHOLD_DIP * ((float) ratio)) * scale + 0.5f);
}
Bitmap bitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Typeface font = Typeface.createFromAsset(context.getAssets(),
"fonts/dotted_font.ttf");
TextPaint mTextPaint=new TextPaint();
mTextPaint.setColor(Color.YELLOW);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(mThreshold);
mTextPaint.setTypeface(font);
StaticLayout mTextLayout = new StaticLayout(string, mTextPaint, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.save();
canvas.translate(text_x, text_y);
mTextLayout.draw(canvas);
canvas.restore();
return bitmap;
}