微信小程序 canvas绘制多行文本(文本换行)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序 canvas绘制多行文本(文本换行)相关的知识,希望对你有一定的参考价值。
参考技术A有什么问题尽管留言~
由于我平时主要使用wepy开发项目 所以这些常用封装及项目架子都是使用的wepy
覆盖了一些常用操作与封装、登录流程、保存图片至相册及相关授权流程
将多行文本绘制到 Canvas
【中文标题】将多行文本绘制到 Canvas【英文标题】:Draw multi-line text to Canvas 【发布时间】:2011-07-20 04:21:40 【问题描述】:一个希望快速的问题,但我似乎找不到任何示例...我想通过Canvas
将多行文本写入自定义View
,并在onDraw()
我有:
...
String text = "This is\nmulti-line\ntext";
canvas.drawText(text, 100, 100, mTextPaint);
...
我希望这会导致换行符,但我看到的是 \n
所在的神秘字符。
任何指针表示赞赏。
保罗
【问题讨论】:
文档建议使用Layout
而不是直接调用Canvas.drawText
。 This Q&A shows how to use a StaticLayout
绘制多行文本。
【参考方案1】:
我找到了另一种使用静态布局的方法。代码在这里供任何人参考:
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();
【讨论】:
我认为更好的解决方案..无需将文本拆分为行..如果文本在开始时没有任何换行符或者我们不知道它是否有换行符.. . 太棒了,它对我有用。我们可以防止大文本超出画布高度吗? 非常有帮助,但是在使 StaticLayout 居中时,请注意如何在 TextPaint() 上设置对齐方式。使用 TextPaing.setTextAlign(Align.CENTER) 给我带来了问题,因为不同的手机会对此做不同的事情。canvas.getWidth()
实际上应该是 getWidth() - getPaddingLeft() - getPaddingRight()
,以说明视图的填充。另外,请注意,只有当您的文本或视图大小发生变化并绘制它时,您才能计算 StaticLayout 而无需构建新的,这可能会更好!
@Eenvincible 你可以在这里查看我的博文:skoumal.net/en/android-drawing-multiline-text-on-bitmap【参考方案2】:
只需遍历每一行:
int x = 100, y = 100;
for (String line: text.split("\n"))
canvas.drawText(line, x, y, mTextPaint);
y += mTextPaint.descent() - mTextPaint.ascent();
【讨论】:
有没有合适的方法来计算新的 y 位置?添加一个看似随机的数字并没有让我感到很舒服...... 如果觉得ascent+decent太小,可以加个常数gap factor,或者乘以(比如乘以1.5行)来品尝。 注意 ascent 是负数。你实际上需要下降-上升来获得高度 您可以获取选定角色的指标,例如font.measure("Y") 这样自己做的问题是,您不能使用 Paint 的 getTextBounds 之类的东西来查找边界框。 Canvas 或 Paint 是否无法通过某种方式了解多行文本框?这似乎是一个很常见的要求。【参考方案3】:不幸的是,Android 不知道\n
是什么。您需要做的是剥离\n
,然后偏移 Y 以使您的文本位于下一行。所以是这样的:
canvas.drawText("This is", 100, 100, mTextPaint);
canvas.drawText("multi-line", 100, 150, mTextPaint);
canvas.drawText("text", 100, 200, mTextPaint);
【讨论】:
所以我必须将文本分成三个单独的块,然后调用三个drawText()
?
是的。我只是添加了一个示例。使用 String.Split 在 '\n's 处拆分,然后偏移每个。
非常感谢您提出这个想法。
Android 确实知道 \n 是什么,只需将其添加到字符串文本中【参考方案4】:
我已经写了完整的例子
颜色.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;
【讨论】:
为什么要使用循环来计算行数?int noOfLines = gText.split("\n").length
【参考方案5】:
这是我基于@Dave 的回答的解决方案(顺便说一句;-))
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,但它并没有真正让你。所以这是一个介于两者之间的课程!
【讨论】:
我试过这种方式.. 一切正常,除了我最大的一行最后一个字最后一个字符只显示了一半。 ?【参考方案6】:我必须在这里添加我的版本,它也考虑了 STROKE WIDTH。
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);
【讨论】:
【参考方案7】:它会起作用的。我测试过
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/
【讨论】:
当我使用位图图像 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.transparent_flag);它工作正常,但如果我使用文本视图 id insted 它将无法工作 谢谢,它完全符合我的要求,但如果你能帮助我编辑其中的文本,或将其滑动到任何其他位置,就像 photo-shop 一样,再次感谢前进。【参考方案8】:是的。使用canvas.getFontSpacing()
作为增量。出于好奇,我自己尝试过,它适用于任何字体大小。
【讨论】:
我想你的意思是Paint.getFontSpacing【参考方案9】:试试这个
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);
【讨论】:
我认为这是在 onDraw 中不要做什么的完美示例。 @rupps 是的,将所有这些都包含在 onDraw 中可能完全是矫枉过正,但答案并没有告诉你这样做。这个想法是天才(它解决了我的问题)。拧上 StaticLayout 和 String.split!【参考方案10】:我重新使用了 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();
【讨论】:
当文本被截断时,您的代码也可能会剪切适合空格的整个单词。因此,这里有一个改进代码的小建议:将三个字符“...”替换为仅包含三个点的字符:“...”(HTML 中的 … 代码)。然后,您可以只删除一个字符(通常是一个空格)而不是三个,并保持您的单词未删减:truncatedText = truncatedText.substring(0, Math.max(0, truncatedText.length() - 1));跨度> 【参考方案11】:没有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;
【讨论】:
你太棒了,伙计!做得好!我真的很喜欢它。一旦达到第一页的限制,您能否帮助扩展您的代码以便能够处理下一页?在我的应用程序中,我使用画布创建 PDF (A4 595x842)。我可以调整页面的宽度,但是如果文本很大,我需要继续下一页等等。非常感谢。【参考方案12】:我使用我所拥有的东西,它已经将单行转换为画布,我处理了 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;
【讨论】:
【参考方案13】:我遇到了类似的问题。但我应该返回文本的路径。 您可以在 Canvas 上绘制此路径。 这是我的代码。我使用中断文本。和path.op
public Path createClipPath(int width, int height)
final Path path = new Path();
if (textView != null)
mText = textView.getText().toString();
mTextPaint = textView.getPaint();
float text_position_x = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
text_position_x = findTextBounds(textView).left;
boolean flag = true;
int line = 0;
int startPointer = 0;
int endPointer = mText.length();
while (flag)
Path p = new Path();
int breakText = mTextPaint.breakText(mText.substring(startPointer), true, width, null);
mTextPaint.getTextPath(mText, startPointer, startPointer + breakText, text_position_x,
textView.getBaseline() + mTextPaint.getFontSpacing() * line, p);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
path.op(p, Path.Op.UNION);
endPointer -= breakText;
startPointer += breakText;
line++;
if (endPointer == 0)
flag = false;
return path;
为了查找文本绑定,我使用了这个函数
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
private Rect findTextBounds(TextView textView)
// Force measure of text pre-layout.
textView.measure(0, 0);
String s = (String) textView.getText();
// bounds will store the rectangle that will circumscribe the text.
Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
// Get the bounds for the text. Top and bottom are measured from the baseline. Left
// and right are measured from 0.
textPaint.getTextBounds(s, 0, s.length(), bounds);
int baseline = textView.getBaseline();
bounds.top = baseline + bounds.top;
bounds.bottom = baseline + bounds.bottom;
int startPadding = textView.getPaddingStart();
bounds.left += startPadding;
// textPaint.getTextBounds() has already computed a value for the width of the text,
// however, Paint#measureText() gives a more accurate value.
bounds.right = (int) textPaint.measureText(s, 0, s.length()) + startPadding;
return bounds;
【讨论】:
【参考方案14】:对于 Kotlin 用户。 可以使用StaticLayout 创建多行文本。在这里找到了一个很好的解释以及如何将其用作扩展功能。 https://medium.com/over-engineering/drawing-multiline-text-to-canvas-on-android-9b98f0bfa16a
【讨论】:
【参考方案15】:除了绘制多行文本之外,您可能还难以获得多行文本边界(例如为了在画布上对齐)。
默认paint.getTextBounds()
在这种情况下将不起作用,因为它将测量唯一的线。
为方便起见,我创建了这两个扩展函数:一个用于绘制多行文本,另一个用于获取文本边界。
private val textBoundsRect = Rect()
/**
* Draws multi-line text on the Canvas with the origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
fun Canvas.drawTextMultiLine(text: String, x: Float, y: Float, paint: Paint)
var lineY = y
for (line in text.split("\n"))
lineY += paint.descent().toInt() - paint.ascent().toInt()
drawText(line, x, lineY, paint)
/**
* Retrieve the text boundary box, taking into account line breaks [\n] and store to [boundsRect].
*
* Return in bounds (allocated by the caller [boundsRect] or default mutable [textBoundsRect]) the smallest rectangle that
* encloses all of the characters, with an implied origin at (0,0).
*
* @param text string to measure and return its bounds
* @param start index of the first char in the string to measure. By default is 0.
* @param end 1 past the last char in the string to measure. By default is test length.
* @param boundsRect rect to save bounds. Note, you may not supply it. By default, it will apply values to the mutable [textBoundsRect] and return it.
* In this case it will be changed by each new this function call.
*/
fun Paint.getTextBoundsMultiLine(
text: String,
start: Int = 0,
end: Int = text.length,
boundsRect: Rect = textBoundsRect
): Rect
getTextBounds(text, start, end, boundsRect)
val linesCount = text.split("\n").size
val allLinesHeight = (descent().toInt() - ascent().toInt()) * linesCount
boundsRect.bottom = boundsRect.top + allLinesHeight
return boundsRect
现在使用它就这么简单: 绘制多行文本:
canvas.drawTextMultiLine(text, x, y, yourPaint)
用于测量文本:
val bounds = yourPaint.getTextBoundsMultiLine(text)
在这种情况下,它将测量从头到尾的所有文本,并使用默认的一旦分配(可变)矩形。 您可以尝试传递额外的参数以获得额外的灵活性。
【讨论】:
【参考方案16】:这是我的解决方案。它并不完美,但对我有用。
public static Bitmap textAsBitmap(String text, float textSize, int textColor)
int lines = 1;
String lineString1 = "", lineString2 = "";
String[] texts = text.split(" ");
if (texts.length > 2)
for (int i = 0; i < 2; i++)
lineString1 = lineString1.concat(texts[i] + " ");
for (int i = 2; i < texts.length; i++)
lineString2 = lineString2.concat(texts[i] + "");
else
lineString1 = text;
lineString1 = lineString1.trim();
lineString2 = lineString2.trim();
String[] lastText = new String[2];
lastText[0] = lineString1;
if (!lineString2.equals(""))
lines = 2;
lastText[1] = lineString2;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(textSize);
paint.setColor(textColor);
paint.setTextAlign(Paint.Align.LEFT);
float baseline = -paint.ascent(); // ascent() is negative
String maxLengthText = "";
if (lines == 2)
if (lineString1.length() > lineString2.length())
maxLengthText = maxLengthText.concat(lineString1);
else
maxLengthText = maxLengthText.concat(lineString2);
else
maxLengthText = maxLengthText.concat(text);
int width = (int) (paint.measureText(maxLengthText) + 0.5f); // round
int height = (int) ((baseline + paint.descent() + 0.5f) * lines);
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
for (int i = 0; i < lines; i++)
canvas.drawText(lastText[i], 0, baseline, paint);
baseline *= lines;
return image;
【讨论】:
【参考方案17】:我为画布中的多行文本设计了一种更好的方法(我不能说它是否更好,但这种方法应该很简单),比如在 SurfaceView 中。
代码如下:
public class MultiLineText implements ObjectListener
private String[] lines;
private float x, y, textSize;
private int textColor;
private float currentY;
public MultiLineText(String[] lines, float x, float y, float textSize, int textColor)
this.lines = lines;
this.x = x;
this.y = y;
this.textSize = textSize;
this.textColor = textColor;
@Override
public void draw(Canvas canvas)
Paint paint = new Paint();
paint.setColor(textColor);
paint.setTextSize(textSize);
currentY = y;
for (int i = 0; i < lines.length; i++)
if (i == 0)
canvas.drawText(lines[i], x, y, paint);
else
currentY = currentY + textSize;
canvas.drawText(lines[i], x, currentY, paint);
@Override
public void update()
使用import android.graphics.Canvas;
和import android.graphics.Paint;
导入2 个类,以确保不会发生错误。
简单地说,创建一个名为“ObjectListener”的接口类(或任何你想调用的,只需更改名称),然后添加以下两行代码:
void draw(Canvas canvas);
void update();
要实现这一点,请在 View 或 Renderer on draw(Canvas canvas)
方法中使用此代码:
new MultiLineText(new String[]
"This is a multi-line text.",
"It's setup is basic. Just do the following code,",
"and you would be done."
, 150, 150, 32, Color.WHITE).draw(canvas);
对不起,我只是想实现这个文本,所以是的...... 您可以根据自己的喜好从 150 更改 X 和 Y 坐标。文本 Size 为 26 是可读的,并且不会太大,因为 Canvas 默认以小文本呈现。
【讨论】:
【参考方案18】:我的动态文本大小和间距示例,非常适合我...
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;
【讨论】:
以上是关于微信小程序 canvas绘制多行文本(文本换行)的主要内容,如果未能解决你的问题,请参考以下文章