Domanda

Ho un TextView con una OnTouchListener. Quello che voglio è l'indice di carattere che l'utente sta puntando a quando ho la MotionEvent. C'è un modo per raggiungere le metriche di carattere sottostanti del TextView?

È stato utile?

Soluzione

Non sono a conoscenza di un semplice modo diretto per fare questo, ma si dovrebbe essere in grado di mettere insieme qualcosa usando il Colore oggetto della TextView tramite una chiamata a TextView.getPaint ()

Una volta ottenuto l'oggetto vernice si avrà accesso alle FontMetrices sottostanti tramite una chiamata a Paint.getFontMetrics () e hanno accesso ad altre funzioni come Paint.measureText () Paint.getTextBounds (), e Paint.getTextWidths () per l'accesso alla dimensione effettiva del testo visualizzato.

Altri suggerimenti

Hai provato qualcosa di simile:

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
}

Spero che questo aiuti ...

Mentre funziona in generale ho avuto alcuni problemi con la risposta di Tony Blues.

In primo luogo i rendimenti getOffsetForHorizontal un offset anche se la coordinata x è ben oltre l'ultimo carattere della riga.

secondo l'offset talvolta carattere restituito appartiene al carattere successivo, non il carattere direttamente sotto al puntatore. A quanto pare il metodo restituisce l'offset della posizione del cursore più vicino. Questo può essere a sinistra oa destra del carattere a seconda di ciò che è più vicino da.

La mia soluzione utilizza getPrimaryHorizontal invece determinare la posizione del cursore di un certo offset e utilizza ricerca binaria per trovare l'offset sotto coordinate x del puntatore.

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

Modifica:. Questa versione aggiornata funziona meglio con interruzioni di riga innaturale, quando una parola lunga non va bene in una linea e viene diviso da qualche parte nel mezzo

Avvertenze: Nei testi scritti con un trattino, cliccando sul segno meno alla fine di una linea di ritorno l'indice del carattere successivo ad essa. Anche questo metodo non funziona bene con i testi RTL.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top