2012-07-22 11 views
19

Básicamente, quiero mostrar un pasaje de texto (potencialmente, bastante largo) y permitir que el usuario haga clic en cualquier palabra. En ese punto, quiero determinar en qué palabra hicieron clic. También quiero obtener la oración completa en la que aparece la palabra (esto es bastante trivial, suponiendo que puedo determinar en qué posición está la palabra dentro del texto).Determinar qué palabra se hace clic en una vista de texto de Android

Idealmente, me gustaría escuchar sólo para un evento onTouch, obtener la X e Y, y decir algo como textView.wordAt(event.x, event.y) o textView.cursorPositionNearest(event.x, event.y), pero parece que no es tan fácil :-)

Mi actual mejor esfuerzo implica el uso de un TextView y crear uno ClickableSpan por palabra. Funciona, pero no es exactamente elegante, y supongo que comenzaría a consumir memoria si lo uso en textos largos.

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

Si alguien tiene una idea mejor, me encantaría escucharla.

Gracias de antemano, de Dave

No sabe cómo se supone que debo realmente para responder a preguntas sobre stackoverflow, pero me las he arreglado para extraer algo de código de la API de Android 15 y modificarlo muy poco que ver lo que necesitaba Gracias a Dheeraj por la sugerencia.

El nuevo código permite que consiga una posición del símbolo basado en una posición de eventos táctiles, a partir de ahí que debería ser capaz de obtener la palabra que se tocó, y la frase que aparece en el código adjunto:.

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

Respuesta

10

Si se dirige al nivel de API 14+, puede usar getOffsetForPosition().

Para la versión anterior de Android, vea si puede copiar el código de este método de la fuente de Android y ampliar su propio TextView.

+0

Suena prometedor. Estoy pre API 14, pero con suerte debería poder obtenerlo del código. Gracias Dheeraj –

+2

Gracias de nuevo Dheeraj. Arranqué el código y funciona muy bien. –

Cuestiones relacionadas