Intereting Posts
Как построить FFMPEG для всей архитектуры Android-устройства? Как получить битмап из drawable, определенного в xml? Может ли addJavascriptInterface () полагаться на getClass ()? Ручное раздувание пользовательского представления дает разные макеты для пользовательского вида ActionBar Проблема с стилем меню переполнения ActionbarSherlock Удаление и добавление действий в задний стек Android-браузер обновляет страницу после выбора файла через элемент ввода Fragment's onActivityCreated () вызывается после onDestroy () действия Как я могу использовать adb для удаления APK с нескольких подключенных устройств? Android.database.sqlite.SQLiteDatabase.rawQuery () не обновляет столбец DATETIME с помощью функции SQLite datetime () Выход из плагина Fabric Разбиение большого текста на страницы в текстовом переключателе android Android Studio: «Выполнение не выполнено для задачи»: app: mergeDebugResources «если проект создан на диске C: Активность Android по блокировке блокировки по умолчанию Требуется разрешение android – call_phone?

Нарисуйте многострочный текст на холст

Надеюсь, быстрый вопрос, но я не могу найти никаких примеров … Я бы хотел написать многострочный текст в пользовательский View через Canvas , а в onDraw() меня есть:

 ... String text = "This is\nmulti-line\ntext"; canvas.drawText(text, 100, 100, mTextPaint); ... 

Я надеялся, что это приведет к разрыву строк, но вместо этого я вижу загадочные символы, где \n будет.

Любые указатели оценили.

Павел

Solutions Collecting From Web of "Нарисуйте многострочный текст на холст"

К сожалению, 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(); } 

Это мое решение, основанное на ответе @ 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, но это действительно не позволяет вам. Так что это промежуточный класс!

Я должен добавить здесь свою версию, которая также рассматривает 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); } } 

Да. Используйте canvas.getFontSpacing() в качестве приращения. Я сам пробовал это из любопытства, и он работает для любого размера шрифта.

Я написал полный пример

Введите описание изображения здесь

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

Я повторно использовал решение, предложенное 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(); } 

попробуй это

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

это будет работать. Я тестировал

  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/

Решение без 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; }