Wie erzwinge ich einen Zeilenumbruch, bevor das letzte Wort einer Zeile den Rand erreicht?

7

Ich drucke einen Schiebetext, indem ich jeden Buchstaben nach kurzer Zeit hinzufüge. Mein Problem ist, dass wenn der Text mehrzeilig ist, das letzte Wort einer Zeile in der aktuellen Zeile beginnt und zum nächsten springt, wenn es zu groß wird, um zu passen, was zu einem hässlichen Effekt führt.

Ich muss also das Wort bestimmen, bei dem die Linie brechen würde, und das vorherige Leerzeichen durch Zeilenumbruch ersetzen, um den Bruch zu erzwingen, bevor das Wort den Rand erreicht. Ich verstehe nicht, wie das geht. Außerdem, wenn es eine Möglichkeit gibt, die libgdx BitmapFontberechnen zu lassen, würde ich gerne lernen.

petervaz
quelle
BitmapFonts haben eine getBoundsMethode: ( libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/graphics/g2d/… Sie können damit überprüfen, wann eine Linie die Umbruchbreite überschreitet .
Anko
1
@Anko yep, und ich kann diese Position verwenden, um den nächsten Leerraum zu finden. Das Problem ist, ich brauche den vorherigen Leerraum und berechne von dort aus erneut für die zweite Zeile, bis der Text vorbei ist. Wie auch immer ich versuche zu visualisieren, das scheint zu komplex und bringt mich zum Schielen = P. Der Text wurde bereits zuvor gezeichnet, daher muss jemand wissen, wie das geht.
Petervaz

Antworten:

6

Grundsätzlich lautet der Algorithmus wie folgt:

  1. Auf maxBreakWickellänge einstellen.
  2. Wenn die Zeichenfolge kürzer als die maximale Unterbrechung ist, geben Sie die Zeichenfolge zurück.
  3. Stellen Sie nextBreakauf maxBreakund newStringauf ""und lastBreakauf0
  4. Überprüfen Sie, ob char at nextBreak ein Unterbrechungszeichen ist (Leerzeichen, neue Zeile usw.).
  5. Wenn char kein Break-Char ist, subtrahieren Sie eines von nextBreakund wiederholen Sie Schritt 4
  6. Wenn char keines der Zeichen break chars ist, müssen Sie die Zeichenfolge teilen, also in Zeilenumbruchlänge, also festlegen nextBreak Länge wickeln
  7. Fügen Sie einen Teilstring von lastBreak-> nextBreakund ein neues Zeilenzeichen hinzunewString
  8. Setze lastBreak= nextBreakund füge Wrap-Länge hinzunextBreak
  9. Fahren Sie mit Schritt 4 fort, bis nextBreakdie ursprüngliche Zeichenfolgenlänge größer ist.

In weniger Worten. Sie möchten mit der maximalen Wickellänge beginnen und rückwärts arbeiten, bis Sie einen Haltepunkt finden. Wenn Sie es finden, fügen Sie ein Zeilenumbruchzeichen ein. Wiederholen Sie dies, bis Sie das Ende Ihrer ursprünglichen Zeichenfolge erreicht haben.

Nun im Code:

public static String wrapString(String string, int charWrap) {
    int lastBreak = 0;
    int nextBreak = charWrap;
    if (string.length() > charWrap) {
        String setString = "";
        do {
            while (string.charAt(nextBreak) != ' ' && nextBreak > lastBreak) {
                nextBreak--;
            }
            if (nextBreak == lastBreak) {
                nextBreak = lastBreak + charWrap;
            }
            setString += string.substring(lastBreak, nextBreak).trim() + "\n";
            lastBreak = nextBreak;
            nextBreak += charWrap;

        } while (nextBreak < string.length());
        setString += string.substring(lastBreak).trim();
        return setString;
    } else {
        return string;
    }
}

Wo stringist die Zeichenfolge, die Sie brechen möchten undcharWrap ist die maximale Anzahl von Zeichen pro Zeile zulässig?

Um herauszufinden, was charWrapsein sollte, möchten Sie wahrscheinlich die durchschnittliche Breite Ihrer Zeichen in Pixel ermitteln und dann sehen, wie viele Sie in den verfügbaren Platz passen können.

MichaelHouse
quelle
Das hat wunderbar funktioniert. Ich erhalte den Wert von charWrapdurch Aufrufen font.computeVisibleGlyphs(text, 0, text.length(), WIDTH), wo WIDTHdie verfügbare Bildschirmgröße ist (Änderungen mit Größenänderung), sodass ich die Anzahl der Zeichen nicht erraten muss, zumindest für die erste Zeile, die noch daran arbeitet =). Ihr Code hat so wie er ist perfekt funktioniert und war eine nette Extrameile, nachdem Sie den Algorithmus gezeigt haben. Vielen Dank.
Petervaz
2
Vielen Dank. Ich habe den Code für mein Spiel geschrieben, also wurde er schon einmal getestet :) Ich mag keine Code-Antworten, deshalb wollte ich sicherstellen, dass er ausreichend erklärt wurde. Ich bin froh, dass es bei dir funktioniert hat.
MichaelHouse