2010-02-25 15 views
18

Mam niestandardową kontrolę, która wykonuje wiele rysunków 2D prosto do canvas.Zawijanie długiego tekstu na płótnie z systemem Android

Niektóre z tego rysunku są tekstem, więc używam metody Canvas.drawText().

Chcę narysować tekst w pewnych granicach - górny lewy, pewna maksymalna szerokość i maksymalna liczba linii. Po narysowaniu tekstu chcę wiedzieć, ile linii zajęło.

Czy jest wbudowana funkcja do rysowania tekstu w granicach, czyniąc podział w sposób rozsądny?

Jeśli nie, czy istnieje standardowy przepis na to?

+0

Zobacz tę odpowiedź dla dobrego przykładu użycia 'StaticLayout's: http://stackoverflow.com/a/8369690/293280 –

Odpowiedz

30

Możesz użyć do tego klasy android.text.StaticLayout; po prostu stwórz StaticLayout dla żądanego tekstu, wyrównania, szerokości itp. i wywołaj metodę draw(Canvas), aby narysować na płótnie.

+0

Zadziwiające, że przeoczyłem to – Will

+0

Czy jest to tylko dla Androida? A co z innymi platformami? –

+0

Świetnie! Jak wyśrodkować tekst na płótnie? –

4

Możesz użyć Paint.getTextBounds(), aby zmierzyć rozmiar całego łańcucha lub Paint.getTextWidths(), aby uzyskać szerokość każdej litery. Następnie należy odpowiednio rozdzielić łańcuch przed jego rysowaniem.

3

Miałem ten sam problem. Jednym z moich pierwszych rozwiązań jest podążanie.

/** 
    * This function draws the text on the canvas based on the x-, y-position. 
    * If it has to break it into lines it will do it based on the max width 
    * provided. 
    * 
    * @author Alessandro Giusa 
    * @version 0.1, 14.08.2015 
    * @param canvas 
    *   canvas to draw on 
    * @param paint 
    *   paint object 
    * @param x 
    *   x position to draw on canvas 
    * @param y 
    *   start y-position to draw the text. 
    * @param maxWidth 
    *   maximal width for break line calculation 
    * @param text 
    *   text to draw 
    */ 
public static void drawTextAndBreakLine(final Canvas canvas, final Paint paint, 
     final float x, final float y, final float maxWidth, final String text) { 
    String textToDisplay = text; 
    String tempText = ""; 
    char[] chars; 
    float textHeight = paint.descent() - paint.ascent(); 
    float lastY = y; 
    int nextPos = 0; 
    int lengthBeforeBreak = textToDisplay.length(); 
    do { 
     lengthBeforeBreak = textToDisplay.length(); 
     chars = textToDisplay.toCharArray(); 
     nextPos = paint.breakText(chars, 0, chars.length, maxWidth, null); 
     tempText = textToDisplay.substring(0, nextPos); 
     textToDisplay = textToDisplay.substring(nextPos, textToDisplay.length()); 
     canvas.drawText(tempText, x, lastY, paint); 
     lastY += textHeight; 
    } while(nextPos < lengthBeforeBreak); 
} 

Czego brakuje:

  • Żaden inteligentny mechanizm Przerwa-line, ponieważ rozkłada na podstawie maxwidth

Jak zadzwonić?

paint.setTextSize(40); 
    paint.setColor(Color.WHITE); 
    paint.setSubpixelText(true); 
    float textHeight = paint.descent() - paint.ascent(); 
    CanvasUtils.drawTextAndBreakLine(canvas, paint, this.left, 
      textHeight, this.displayWidth, this.text); 

Mam klasę statyczną o nazwie CanvasUtils, w której hermetyzuję takie rzeczy. Zasadniczo narysuję tekst w prostokącie. Z tego powodu textHeight jest wysokością tekstu. Ale możesz przekazać to, co chcesz, do funkcji.

Dobre programowanie!

+0

Tak, to zadziałało, ale zmusiło słowa do zerwania! Czy istnieje sposób, aby to naprawić? – Eenvincible

+0

Hej, Eenvincible, masz na myśli pojedyncze słowa? Dzielenie? –

+0

Nie w szczególności. co dzieje się z tym kodem jest to, że tekst owija się poprawnie w obrębie prostokąta, ale niektóre słowa zostają odcięte, kończąc na łamaniu nowych linii z częścią słów wyświetlaną w jednym wierszu i jej częścią w następnym wierszu. – Eenvincible