Android ClickableSpan get text onClick()
Asked Answered
D

4

20

I'm working on ClickableSpan in a TextView, and I'm trying to get the clicked span's text. This is my code.

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

As you can see, I set the clickablespan to the TextView from characters 12 to 17, and I want to get these characters in the onClick event.

Is there anyway I can do that? Or at least can I pass the 12, 17 parameter to onClick event?

Thank you!

Destined answered 3/11, 2013 at 6:36 Comment(0)
S
41

try this:

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) + "]");
    }
}
Succinct answered 3/11, 2013 at 7:18 Comment(3)
sure, it does... add the checks mentioned in.// TODOsSuccinct
works even for multiple clickable words :) thanks! But why does it work? so the OnClick receives view which is the textview, then doing tv.getText returns the clicked Spanned object even if there were other Spannable words. How is this working? @SuccinctGasman
@Gasman tv.getText() is a Spanned object, Spanned object can have multiple spans not SpannablesSuccinct
J
5

A little simpler, could also pass a model reference if necessary.

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 + "]");
    }
}

Then call new SpecialClickableSpan("My Text")

Juvenescence answered 30/1, 2014 at 22:34 Comment(0)
J
4

Edited: previous code was wrong, this works

    // 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();
                }
            }
        }
    };
Jensen answered 3/11, 2013 at 7:7 Comment(3)
Are you sure about this? I have not run your code yet but it seems not to work... your sannableText is not being used, spanStr have not been defined. And by the way, textView.getText() return a CharSequence, not a SpannableStringBuilder... Could you please check again?Destined
I mean spannableText instead of spanStr. I did from head, I'm doing a real code now and update in a while.Jensen
I was thinking in SpannedText also, instead of SpannableStringBuilder. Anyway, you're right, this doesn't work. getSpans is for Editable (EditText, not TextView)Jensen
Z
0

You can also use to make string spannable like this

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

and CustomerTextClick will be

private static class CustomerTextClick extends 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
    }
}

Tested and working code.

Zabaglione answered 6/4, 2016 at 8:19 Comment(1)
You can also use click listener directly in for loop as 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); }Zabaglione

© 2022 - 2024 — McMap. All rights reserved.