Определение того, какое слово нажимается в текстовом представлении Android
По сути, я хочу отобразить отрывок текста (возможно, довольно длинный) и позволить пользователю щелкнуть любое слово. На этом этапе я хочу определить, какое слово они нажимали. Я также хочу получить полное предложение, в котором появляется слово (это довольно тривиально, если предположить, что я могу определить, в каком положении находится слово в тексте).
В идеале я бы просто послушал событие onTouch, получил бы X и Y и сказал бы что-то вроде textView.wordAt(event.x, event.y)
или же textView.cursorPositionNearest(event.x, event.y)
, но, кажется, это не так просто:-)
В настоящее время я стараюсь использовать TextView и создавать по одному ClickableSpan на слово. Это работает, но это не совсем элегантно, и я предполагаю, что это начнёт съедать память, если я буду использовать это для длинных текстов.
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();
}
}
Если у кого-то есть идея получше, я бы хотел ее услышать.
Заранее спасибо, Дейв
Не уверен, как я действительно должен отвечать на вопросы о stackru, но мне удалось вырвать некоторый код из Android 15 API и немного изменить его, чтобы сделать то, что мне нужно. Спасибо Deeraj за предложение.
Новый код позволяет мне получить позицию каретки, основанную на позиции события касания, оттуда я должен быть в состоянии получить слово, к которому прикоснулись, и предложение, в котором оно появляется. Код прилагается:
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);
}
1 ответ
Если вы нацелены на уровень API 14+, вы можете использовать getOffsetForPosition()
,
Для предыдущей версии Android посмотрите, можете ли вы скопировать код для этого метода из исходного кода Android и расширить свой собственный TextView.