Android ClickableSpan点击事件获取文本onClick()。

20

我正在TextView中研究ClickableSpan,并且尝试获取所点击的span的文本。这是我的代码。

// this is the text we'll be operating on
SpannableString text = new SpannableString("Lorem ipsum dolor sit amet");

// make "dolor" (characters 12 to 17) display a toast message when touched
ClickableSpan clickableSpan = new ClickableSpan() {
    @Override
    public void onClick(View view) {
        // This will get "Lorem ipsum dolor sit amet", but I just want "dolor"
        String text = ((TextView) view).getText().toString(); 
        Toast.makeText(context, text, Toast.LENGTH_LONG).show();
    }
};

text.setSpan(clickableSpan, 12, 17, 0);

正如您所看到的,我将 clickablespan 设置为从第12个字符到第17个字符的 TextView ,并且我希望在 onClick 事件中获取这些字符。

有没有任何办法可以做到这一点?或者至少能否将 12, 17 参数传递给 onClick 事件?

谢谢!

4个回答

41

试试这个:

public class LoremIpsumSpan extends ClickableSpan {
    @Override
    public void onClick(View widget) {
        // TODO add check if widget instanceof TextView
        TextView tv = (TextView) widget;
        // TODO add check if tv.getText() instanceof Spanned
        Spanned s = (Spanned) tv.getText();
        int start = s.getSpanStart(this);
        int end = s.getSpanEnd(this);
        Log.d(TAG, "onClick [" + s.subSequence(start, end) + "]");
    }
}

1
当然可以...添加上述检查//待办事项 - pskink
2
即使对于多个可点击的单词也适用 :) 谢谢!但这是如何工作的?因此,OnClick接收到视图,即TextView,然后使用tv.getText返回所点击的Spanned对象,即使有其他Spannable单词也是如此。这是如何运作的呢?@pskink - fersarr
1
@fersarr tv.getText() 是一个 Spanned 对象,Spanned 对象可以有多个 spans,而不是 Spannables。 - pskink

5

如果需要,也可以传递模型引用来简化操作。

public class SpecialClickableSpan extends ClickableSpan {

    String text;

    public SpecialClickableSpan(String text){
         super();
         this.text = text;
    }

    @Override
    public void onClick(View widget) {
         Log.d(TAG, "onClick [" + text + "]");
    }
}

然后调用新的SpecialClickableSpan("My Text")。

4

编辑:之前的代码有误,现在已经修正

    // make "dolor" (characters 12 to 17) display a toast message when touched
    ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View view) {
            TextView textView = (TextView) view;
            CharSequence charSequence = textView.getText();
            if (charSequence instanceof Spannable) {
                Spannable spannableText = (Spannable)charSequence;
                ClickableSpan[] spans = spannableText.getSpans(0, textView.length(), ClickableSpan.class);
                for (ClickableSpan span : spans) {
                    int start = spannableText.getSpanStart(span);
                    int end = spannableText.getSpanEnd(span);
                    Toast.makeText(MainActivity.this, charSequence.subSequence(start, end), Toast.LENGTH_LONG).show();
                }
            }
        }
    };

你确定吗?我还没有运行你的代码,但它似乎不起作用...你的sannableText没有被使用,spanStr也没有被定义。顺便说一下,textView.getText()返回一个CharSequence,而不是SpannableStringBuilder...你能再检查一下吗? - Tony Dinh
我是指spannableText而不是spanStr。我已经从头开始做了,现在正在编写真正的代码,并稍后更新。 - Douglas Drumond Kayama
我也在考虑使用SpannedText,而不是SpannableStringBuilder。无论如何,你是正确的,这样做不起作用。getSpans仅适用于Editable(EditText,而不是TextView)。 - Douglas Drumond Kayama

0

你也可以像这样使用来使字符串可跨度

String htmlLinkText = "Lorem ipsum <a href='http://www.google.com'>dolor</a> sit amet";
    testView.setText(Html.fromHtml(htmlLinkText));
    testView.setMovementMethod(LinkMovementMethod.getInstance());

    CharSequence text = testView.getText();
    if (text instanceof Spannable) {
        int end = text.length();
        Spannable sp = (Spannable) testView.getText();
        URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
        SpannableStringBuilder style = new SpannableStringBuilder(text);
        style.clearSpans();//should clear old spans
        for (URLSpan url : urls) {
            CustomerTextClick click = new CustomerTextClick(url.getURL());
            style.setSpan(click, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        testView.setText(style);
    }

CustomerTextClick 将会是:

私有静态类 CustomerTextClick 继承自 ClickableSpan {

    private String mUrl;

    CustomerTextClick(String url) {
        mUrl = url;
    }

    @Override
    public void onClick(View widget) {
        // TODO Auto-generated method stub
        //Toast.makeText(ctx, "hello google!",Toast.LENGTH_LONG).show();
        // Do your action here
    }
}

经过测试的可用代码。


您也可以直接在for循环中使用点击监听器,如下所示:for (URLSpan url : urls) { CustomerTextClick click = new CustomerTextClick(url.getURL()); style.setSpan(new ClickableSpan() { @Override public void onClick(View widget) { } }, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - Harsh Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接