2012-07-22 14 views
19

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

risposta

10

Se hai impostato il livello API 14+, potresti utilizzare getOffsetForPosition().

Per la precedente versione di Android, vedere se è possibile copiare il codice per questo metodo dalla sorgente Android ed estendere il proprio TextView.

+0

Suoni promettenti. Sono pre API 14, ma si spera che dovrebbe essere in grado di ottenerlo dal codice. Grazie Dheeraj –

+2

Grazie ancora Dheeraj. Ho strappato il codice e funziona molto bene. –

Problemi correlati