In pratica, voglio visualizzare un passaggio di testo (potenzialmente un testo lungo) e consentire all'utente di fare clic su qualsiasi parola. A quel punto, voglio determinare su quale parola hanno cliccato. Voglio anche ottenere l'intera frase in cui appare la parola (questo è piuttosto banale, assumendo che io possa determinare in quale posizione si trova la parola all'interno del testo).Determinare quale parola viene cliccata in una vista testo Android
Idealmente, vorrei solo ascoltare per un evento onTouch, ottenere il X e Y, e dire qualcosa come textView.wordAt(event.x, event.y)
o textView.cursorPositionNearest(event.x, event.y)
, ma sembra non è così facile :-)
Il mio miglior sforzo corrente comporta utilizzando un TextView e creazione di uno ClickableSpan per parola. Funziona, ma non è esattamente elegante, e immagino che inizierebbe a mangiare memoria se lo uso su testi più lunghi.
private final String text = "This is the text";
private TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_view);
textView = (TextView) findViewById(R.id.text_view);
SpannableString ss = new SpannableString(text);
// create spans for "this", "is", "the" and "text"
ss.setSpan(new IndexedClickableSpan(0, 4), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new IndexedClickableSpan(5, 7), 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new IndexedClickableSpan(8, 11), 8, 11, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new IndexedClickableSpan(12, 16), 12, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
}
private final class IndexedClickableSpan extends ClickableSpan {
int startIndex, endIndex;
public IndexedClickableSpan(int startIndex, int endIndex) {
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void onClick(View widget) {
String word = TextViewActivity.this.text.substring(startIndex, endIndex);
Toast.makeText(TextViewActivity.this, "You clicked on " + word, Toast.LENGTH_SHORT).show();
}
}
Se qualcuno ha un'idea migliore, mi piacerebbe sentirlo.
Grazie in anticipo, Dave
Non sono sicuro di come sto davvero dovuto rispondere a domande su StackOverflow, ma sono riuscito a strappare un certo codice di Android 15 API e modificarlo leggermente per fare quello di cui avevo bisogno. Grazie a Dheeraj per il suggerimento.
Il nuovo codice mi permette di ottenere una posizione di accento circonflesso sulla base di una posizione di evento di tocco, da lì dovrei essere in grado di ottenere la parola che è stato toccato, e la frase appare in codice allegato:.
public int getOffsetForPosition(TextView textView, float x, float y) {
if (textView.getLayout() == null) {
return -1;
}
final int line = getLineAtCoordinate(textView, y);
final int offset = getOffsetAtCoordinate(textView, line, x);
return offset;
}
private int getOffsetAtCoordinate(TextView textView2, int line, float x) {
x = convertToLocalHorizontalCoordinate(textView2, x);
return textView2.getLayout().getOffsetForHorizontal(line, x);
}
private float convertToLocalHorizontalCoordinate(TextView textView2, float x) {
x -= textView2.getTotalPaddingLeft();
// Clamp the position to inside of the view.
x = Math.max(0.0f, x);
x = Math.min(textView2.getWidth() - textView2.getTotalPaddingRight() - 1, x);
x += textView2.getScrollX();
return x;
}
private int getLineAtCoordinate(TextView textView2, float y) {
y -= textView2.getTotalPaddingTop();
// Clamp the position to inside of the view.
y = Math.max(0.0f, y);
y = Math.min(textView2.getHeight() - textView2.getTotalPaddingBottom() - 1, y);
y += textView2.getScrollY();
return textView2.getLayout().getLineForVertical((int) y);
}
Suoni promettenti. Sono pre API 14, ma si spera che dovrebbe essere in grado di ottenerlo dal codice. Grazie Dheeraj –
Grazie ancora Dheeraj. Ho strappato il codice e funziona molto bene. –