Android: Come determinare indice di carattere della posizione un tocco di evento in TextView?
-
21-09-2019 - |
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
?
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.