Android: Wie kann man den Charakterindex der Position eines Touch -Ereignisses in TextView bestimmen?

StackOverflow https://stackoverflow.com/questions/2302867

Frage

Ich habe ein TextView mit einem OnTouchListener. Was ich will, ist der Charakterindex, auf den der Benutzer zeigt, wann ich das bekomme MotionEvent. Gibt es eine Möglichkeit, zu den zugrunde liegenden Schriftartmetriken der zu gelangen TextView?

War es hilfreich?

Lösung

Mir ist eine einfache direkte Möglichkeit, dies zu tun, nicht bewusst, aber Sie sollten in der Lage sein, etwas mit dem zusammenzustellen Farbe Objekt des Textviews über einen Aufruf an TextView.getPaint ()

Sobald Sie das Lackobjekt haben, haben Sie Zugriff auf die zugrunde liegenden Schriftmeter über einen Anruf bei Paint.getFontMetrics () und Zugriff auf andere Funktionen wie Paint.measuretext () Paint.GetTextBounds () und Paint.GetTextwidths (), um auf das zuzugreifen Tatsächliche Größe des angezeigten Textes.

Andere Tipps

Haben Sie so etwas ausprobiert:

Layout layout = this.getLayout();
if (layout != null)
{
    int line = layout.getLineForVertical(y);
    int offset = layout.getOffsetForHorizontal(line, x);

    // At this point, "offset" should be what you want - the character index
}

Hoffe das hilft...

Während es im Allgemeinen funktioniert, hatte ich ein paar Probleme mit der Antwort von Tony Blues.

zuerst GetOffsetforHorizontal Gibt einen Offset zurück, auch wenn die X -Koordinate weit über den letzten Charakter der Linie hinausgeht.

Zweitens gehört der zurückgegebene Zeichenversatz manchmal zum nächsten Charakter, nicht zum Charakter direkt unter dem Zeiger. Anscheinend gibt die Methode den Versatz der nächsten Cursorposition zurück. Dies kann links oder rechts vom Charakter sein, je nachdem, was näher durch ist.

Meine Lösung verwendet GetPrimaryHorizontal Bestimmen Sie stattdessen die Cursorposition eines bestimmten Versatzes und verwendet eine binäre Suche, um den Offset unter der X -Koordinate des Zeigers zu finden.

public static int getCharacterOffset(TextView textView, int x, int y) {
    x += textView.getScrollX() - textView.getTotalPaddingLeft();
    y += textView.getScrollY() - textView.getTotalPaddingTop();

    final Layout layout = textView.getLayout();

    final int lineCount = layout.getLineCount();
    if (lineCount == 0 || y < layout.getLineTop(0) || y >= layout.getLineBottom(lineCount - 1))
        return -1;

    final int line = layout.getLineForVertical(y);
    if (x < layout.getLineLeft(line) || x >= layout.getLineRight(line))
        return -1;

    int start = layout.getLineStart(line);
    int end = layout.getLineEnd(line);

    while (end > start + 1) {
        int middle = start + (end - start) / 2;

        if (x >= layout.getPrimaryHorizontal(middle)) {
            start = middle;
        }
        else {
            end = middle;
        }
    }

    return start;
}

Bearbeiten: Diese aktualisierte Version funktioniert besser mit unnatürlichen Zeilenpausen, wenn ein langes Wort nicht in eine Zeile passt und irgendwo in der Mitte geteilt wird.

Vorbehalte: In beistrichenen Texten gibt es am Ende einer Zeile auf den Bindestrich zurück, den Index des Charakters daneben daneben zurückgeben. Auch diese Methode funktioniert nicht gut mit RTL -Texten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top