android - 确定在 android textview 中单击了哪个单词

标签 android textview

基本上,我想显示一段文本(可能是很长的文本),并允许用户单击任何单词。那时,我想确定他们点击了哪个词。我还想得到单词出现的整个句子(这很简单,假设我可以确定单词在文本中的位置)。

理想情况下,我只需要监听 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();
    }
}

如果有人有更好的想法,我很想听听。

提前致谢, 戴夫

不确定我应该如何回答有关 stackoverflow 的问题,但我已经设法从 Android 15 API 中提取了一些代码,并对其稍作修改以完成我需要的操作。感谢 Dheeraj 的建议。

新代码允许我根据触摸事件位置获取插入符号位置,从那里我应该能够获取被触摸的单词,以及它出现的句子。附加代码:

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

最佳答案

如果您的目标是 API 级别 14+,您可以使用 getOffsetForPosition() .

对于以前的Android版本,看看你是否可以从Android源中复制这个方法的代码并扩展你自己的TextView。

关于android - 确定在 android textview 中单击了哪个单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11601139/

相关文章:

android - 如何在 Android 中更改 Button 小部件的文本?

android - 如何在 ImageButton 中设置 onClick 事件?

java - 如何在 Android 中将 TextView 放置在 LinearLayout 的上边缘?

android - 更改所选和按下的 ListView 项目的颜色

java - 在 DialogFragment 中膨胀类 fragment 时出错

android - 可以混淆/加密 SharedPreferences 文件吗?

android - 如何在Android的TextView中使文本居中垂直在一行中

Android:复合控件中的按钮干扰 ListView 的上下文菜单

android - 动画添加到 Nexus4 与其他设备上的 Activity 的新 TextView 的问题

java - 如何在谷歌地图上显示带有坐标的数组列表?