Custom clickable links in TextView
Often we need to display text with clickable links inside TextView. Something like this:
This can be easily done with android:linksClickable=”true”
and android:autoLink=”all"
attributes or Linkify.addLinks()
method. Using these techniques we can handle different url schemas. For example, open https
links in browser and tel
schemas in phone dialer.
But this approach have some disadvantages. For example, by using above mentioned xml-attributes this link would not work:
<string name="text_with_link">By continuing you agree with service <a href="http://www.google.com">Terms of use</a></string>
To make it work, you should use following code instead of attributes:
textView.setMovementMethod(LinkMovementMethod.getInstance());
Now our link will be highlighted and clickable. But what if you want not only open links in browser, but run some custom logic? For example, log event to analytics or open another Activity
on link click.
ClickableSpan
We can use ClickableSpan
class to achieve our goal. This is an abstract class. So we need to subclass it and override onClick()
method. After that we can attach instance of our ClickableSpan
to SpannableString
using setSpan()
method for later use in TextView
.
Something like this:
ClickableSpan clickableSpan = ... // create custom ClickableSpanSpannable spannableText = new SpannableString("Clickable text");
spannableText.setSpan(clickableSpan, 0, spannableText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);textView.setText(spannableText);
To make this code more handy, lets create ClickSpan
class that inherits from ClickableSpan
This class should help us to add clickable links to TextView
with custom handlers in an easy manner. I’ve ended up with following Java implementation:
As we can see, our class defines OnClickListener
interface with single onClick()
method which will be used to handle clicks. Also our class contains two static clickify()
methods, that we can used to easily attach links to TextView. All you need to do, is to pass TexView
with String
you want to wrap with link and instance of OnClickListener
By default, links are drawn underlined. Sometimes this is not desired behaviour. If we want to draw our links without underline, we can use second clickify()
method, which receives boolean parameter withUnderline
and pass false value.
Now we can use our ClickSpan
class. Firstly lets define texts inside strings.xml:
After that we can add links to TextView
with following code (written in Kotlin):
Now we can define any logic inside our handlers.
Conclusion
Links handling inside TextView can be done by using different approaches. You can use framework-provided classes and xml-attributes. For many cases they work just fine.
But if you want to implement custom links handling, it may be required to write some code. I have used above mentioned ClickSpan
class in many projects and it just works. It is small and can be easily changed to your needs.