Gambar teks multi-baris ke Canvas

124

Sebuah pertanyaan yang mudah-mudahan cepat, tetapi saya tidak dapat menemukan contoh apa pun ... Saya ingin menulis teks multi-baris ke kustom Viewmelalui a Canvas, dan di onDraw()saya punya:

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

Saya berharap ini akan menghasilkan jeda baris, tetapi sebaliknya saya melihat karakter samar di mana \nitu.

Setiap petunjuk dihargai.

Paul

Paul Mennega
sumber
1
Dokumentasi merekomendasikan penggunaan a Layoutdaripada menelepon Canvas.drawTextsecara langsung. T&J ini menunjukkan cara menggunakan aStaticLayout untuk menggambar teks multiline.
Suragch

Jawaban:

26

Sayangnya Android tidak tahu apa \nitu. Apa yang harus Anda lakukan adalah menghapus \ndan mengimbangi Y untuk mendapatkan teks Anda di baris berikutnya. Jadi seperti ini:

canvas.drawText("This is", 100, 100, mTextPaint);
canvas.drawText("multi-line", 100, 150, mTextPaint);
canvas.drawText("text", 100, 200, mTextPaint);
Icemanind
sumber
1
Jadi saya harus memecah teks menjadi tiga bagian terpisah, lalu memiliki tiga panggilan ke drawText()?
Paul Mennega
5
Iya. Saya baru saja menambahkan contoh. Gunakan String.Split untuk memisahkan di '\ n dan kemudian offset masing-masing.
Icemanind
Terima kasih banyak atas ide ini.
Sumit Kumar
224

Saya menemukan cara lain menggunakan tata letak statis. Kode di sini untuk dirujuk siapa saja:

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();
GreenBee
sumber
3
solusi yang lebih baik menurut pendapat saya .. tidak perlu membagi teks menjadi baris .. Terutama nyaman jika teks tidak memiliki jeda baris di awal atau kami tidak tahu apakah ada ...
Ewoks
6
Luar biasa, itu berhasil untuk saya. Bisakah kita mencegah teks besar keluar dari ketinggian kanvas?
moDev
1
Sangat membantu, tetapi saat memusatkan StaticLayout, berhati-hatilah tentang cara Anda menyetel perataan pada TextPaint (). Menggunakan TextPaing.setTextAlign (Align.CENTER) menyebabkan masalah bagi saya karena ponsel yang berbeda akan melakukan hal yang berbeda dengan ini.
greg7gkb
2
canvas.getWidth()harus benar-benar getWidth() - getPaddingLeft() - getPaddingRight(), untuk memperhitungkan padding tampilan. Selain itu, perhatikan bahwa Anda dapat menghitung StaticLayout hanya saat teks atau ukuran tampilan Anda berubah dan menggambarnya tanpa membuat yang baru, yang mungkin lebih baik!
Jules
1
@Eenvincible Anda dapat memeriksa posting blog saya di sini: skoumal.net/en/android-drawing-multiline-text-on-bitmap
gingo
98

Lakukan iterasi melalui setiap baris:

int x = 100, y = 100;
for (String line: text.split("\n")) {
      canvas.drawText(line, x, y, mTextPaint);
      y += mTextPaint.descent() - mTextPaint.ascent();
}
Dave
sumber
Apakah ada cara yang layak untuk menghitung posisi y baru? Menambahkan nomor yang tampaknya acak tidak membuat saya merasa sangat nyaman ...
AgentKnopf
1
Jika Anda merasa pendakian + layak terlalu kecil, Anda dapat menambahkan faktor jarak konstan, atau mengalikannya (misalnya dengan 1,5 baris) sesuai selera.
Dave
1
perhatikan bahwa pendakian negatif. Anda sebenarnya membutuhkan pendakian untuk mendapatkan ketinggian
Amir Uval
1
Anda bisa mendapatkan metrik untuk karakter yang dipilih, misalnya font.measure ("Y")
GregD
11

Saya telah menulis contoh lengkap

masukkan deskripsi gambar di sini

colors.xml

  <color name="transparentBlack">#64000000</color>

kelas 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;
    }
}
Siddhpura Amit
sumber
4
Mengapa Anda menggunakan loop untuk menghitung baris? int noOfLines = gText.split("\n").length
Tomasz
9

Ini adalah solusi saya yang didasarkan pada jawaban @ Dave (terima kasih 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();
        }
    }
}

Saya mencoba mewarisi Canvas, tetapi itu tidak benar-benar membiarkan Anda. Jadi ini kelas di antara!

noelicus
sumber
1
Saya mencoba cara ini .. semuanya bekerja dengan baik kecuali baris terbesar saya, kata terakhir, karakter terakhir hanya ditampilkan setengah. ?
Aada
8

Saya harus menambahkan di sini versi saya yang mempertimbangkan STROKE WIDTH juga.

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);
   }
}
Lumis
sumber
6

itu akan berhasil. saya diuji

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

Sumber: http://www.skoumal.net/en/android-drawing-multiline-text-on-bitmap/

Premkumar Manipillai
sumber
sementara saya menggunakan Bitmap image = BitmapFactory.decodeResource (mContext.getResources (), R.drawable.transparent_flag); itu berfungsi dengan baik tetapi jika saya menggunakan id tampilan teks yang dipasang itu tidak akan berfungsi
DKV
Terima kasih, ini berfungsi tepat seperti yang saya inginkan, tetapi jika Anda dapat membantu saya mengedit teks di dalamnya, atau menggesernya ke posisi lain, seperti yang dilakukan toko foto sekali lagi terima kasih sebelumnya.
kvadityaaz
5

Iya. Gunakan canvas.getFontSpacing()sebagai kenaikan. Saya sudah mencobanya sendiri karena penasaran dan berfungsi untuk semua ukuran font.

Richard
sumber
2
Saya pikir yang Anda maksud adalah Paint.getFontSpacing
Jose M.
5

coba ini

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);
Sunil Kumar
sumber
6
Saya pikir ini adalah contoh sempurna tentang apa yang TIDAK boleh dilakukan di onDraw.
rupps
@rupps Ya, mungkin terlalu berlebihan untuk memasukkan semua ini ke dalam onDraw, tetapi jawabannya tidak meminta Anda untuk melakukannya. Dan idenya jenius (dan itu memecahkan masalah saya). Sekrup StaticLayout dan String.split!
Rodia
4

Saya menggunakan kembali solusi yang diusulkan oleh GreenBee dan membuat fungsi untuk menggambar beberapa teks multi baris ke dalam batas-batas tertentu dengan "..." di bagian akhir jika terjadi pemotongan:

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();
    }
androidseb
sumber
3
Saat teks terpotong, kode Anda dapat memotong seluruh kata yang sesuai dengan spasi juga. Jadi, berikut ini adalah saran kecil untuk meningkatkan kode Anda: ganti tiga karakter "..." dengan hanya satu yang berisi tiga titik: "…" (kode & hellip; dalam HTML). Anda kemudian dapat menghapus hanya satu karakter (yang seringkali berupa spasi) dan bukan tiga, dan biarkan kata Anda tidak dipotong: truncatedText = truncatedText.substring (0, Math.max (0, truncatedText.length () - 1));
Asterius
2

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

            }
        }
    }
Roma
sumber
2

Saya bekerja dengan apa yang saya miliki, yang telah mengubah satu baris menjadi kanvas, dan saya mengerjakan jawaban Lumis, dan saya berakhir dengan ini. 1.3 dan 1.3f dimaksudkan sebagai padding antar baris, relatif terhadap ukuran fonta.

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;
}
Peter Griffin
sumber
0

Saya menghadapi masalah serupa. tapi saya harus mengembalikan jalur teks. Anda dapat menggambar jalur ini di atas Kanvas. ini kode saya. Saya menggunakan Break Text. dan 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;
        }

dan untuk menemukan teks terikat saya menggunakan fungsi ini

    @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;
}
mohandes
sumber
0

Selain menggambar teks multiline, seseorang mungkin kesulitan mendapatkan batas teks multiline (misalnya untuk meratakannya di kanvas).
Default paint.getTextBounds()tidak akan berfungsi dalam kasus ini karena ini akan mengukur satu-satunya baris.

Untuk kenyamanan, saya membuat 2 fungsi ekstensi ini: satu untuk menggambar teks multiline, dan yang lainnya untuk mendapatkan batas teks.

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
}

Sekarang menggunakannya semudah itu: Untuk menggambar teks multiline:

canvas.drawTextMultiLine(text, x, y, yourPaint)

Untuk mengukur teks:

val bounds = yourPaint.getTextBoundsMultiLine (teks)

Dalam hal ini, itu akan mengukur semua teks dari awal sampai akhir dan dengan menggunakan Rect default sekali dialokasikan (bisa berubah).
Anda dapat bermain-main dengan melewatkan parameter ekstra untuk fleksibilitas ekstra.

Leo Droidcoder
sumber
-1

Contoh saya dengan Dynamic Text Sizing dan spacing, Berfungsi bagus untuk saya ...

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