TextView
clickable text
Android development
user interface
mobile app development

How to click or tap on a TextView text

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Making text interactive is one of the most common requirements in Android development. Whether you need the entire TextView to respond to taps or only specific words within it to be clickable, Android provides several mechanisms to accomplish this. Understanding which approach to use and why saves you from fighting unexpected behavior around click feedback, focus, and text selection.

Making the Entire TextView Clickable

The simplest case is when the whole TextView should act like a button. You attach a click listener just as you would with any other View.

In Kotlin:

kotlin
1val textView = findViewById<TextView>(R.id.myTextView)
2textView.setOnClickListener {
3    Toast.makeText(this, "TextView clicked!", Toast.LENGTH_SHORT).show()
4}

In Java:

java
1TextView textView = findViewById(R.id.myTextView);
2textView.setOnClickListener(v -> {
3    Toast.makeText(this, "TextView clicked!", Toast.LENGTH_SHORT).show();
4});

If you want the TextView to show a ripple effect when tapped, add the android:clickable="true" and android:focusable="true" attributes in your XML, along with a selectable background:

xml
1<TextView
2    android:id="@+id/myTextView"
3    android:layout_width="wrap_content"
4    android:layout_height="wrap_content"
5    android:text="Tap me"
6    android:clickable="true"
7    android:focusable="true"
8    android:background="?attr/selectableItemBackground" />

Making Specific Words Clickable with ClickableSpan

Sometimes only a portion of the text should be tappable, for example a "Terms of Service" link inside a longer sentence. This is where ClickableSpan comes in. It lets you mark a range of characters as individually clickable.

kotlin
1val fullText = "I agree to the Terms of Service and Privacy Policy"
2val spannable = SpannableString(fullText)
3
4val termsSpan = object : ClickableSpan() {
5    override fun onClick(widget: View) {
6        // Navigate to Terms of Service
7    }
8
9    override fun updateDrawState(ds: TextPaint) {
10        super.updateDrawState(ds)
11        ds.isUnderlineText = true
12        ds.color = Color.BLUE
13    }
14}
15
16val termsStart = fullText.indexOf("Terms of Service")
17spannable.setSpan(termsSpan, termsStart, termsStart + "Terms of Service".length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
18
19val textView = findViewById<TextView>(R.id.myTextView)
20textView.text = spannable
21textView.movementMethod = LinkMovementMethod.getInstance()
22textView.highlightColor = Color.TRANSPARENT

The call to LinkMovementMethod.getInstance() is critical. Without it, Android does not route touch events to the spans inside the text. The highlightColor setting removes the default blue highlight rectangle that appears on tap, which often looks unpolished.

If your text contains URLs, phone numbers, or email addresses that should be clickable without manual span work, Android can detect and linkify them automatically.

In XML:

xml
1<TextView
2    android:id="@+id/autoLinkText"
3    android:layout_width="wrap_content"
4    android:layout_height="wrap_content"
5    android:autoLink="web|email|phone"
6    android:text="Visit https://example.com or email us at [email protected]" />

Programmatically in Kotlin:

kotlin
val textView = findViewById<TextView>(R.id.autoLinkText)
textView.text = "Call us at 555-123-4567 or visit https://example.com"
Linkify.addLinks(textView, Linkify.WEB_URLS or Linkify.PHONE_NUMBERS)

The Linkify utility scans the text with pattern matchers and wraps detected items in URLSpan instances. It also sets the movement method for you. The android:autoLink attribute does the same thing declaratively.

Controlling Click Feedback and Highlight Color

By default, when a user taps a ClickableSpan, Android draws a translucent highlight over the text. You can customize or remove this:

kotlin
1// Remove highlight entirely
2textView.highlightColor = Color.TRANSPARENT
3
4// Use a custom highlight color
5textView.highlightColor = Color.parseColor("#33FF6600")

For the entire-TextView-click scenario, the ?attr/selectableItemBackground drawable gives you a Material ripple. For span-level clicks, the highlight color is the primary visual feedback mechanism.

Common Pitfalls

  • Forgetting LinkMovementMethod: ClickableSpan silently does nothing without it, leading to frustrating debugging sessions.
  • Conflict between setOnClickListener and ClickableSpan: If both are set, tapping a non-span area triggers the View click, but tapping a span triggers only the span. This inconsistency confuses users if not handled intentionally.
  • Not setting highlightColor to transparent: The default blue highlight rectangle looks like a visual bug in most modern app designs.
  • Using autoLink with manually set spans: autoLink can overwrite your custom SpannableString, destroying your carefully placed ClickableSpans. Apply autoLink first or use Linkify programmatically with care.
  • Accessibility oversight: ClickableSpans should describe their action for screen readers. Override updateDrawState to visually distinguish links and ensure TalkBack can announce them.

Summary

  • Use setOnClickListener when the entire TextView should respond to taps, and add selectableItemBackground for ripple feedback.
  • Use ClickableSpan with LinkMovementMethod to make individual words or phrases tappable within a larger block of text.
  • Use android:autoLink or Linkify to automatically detect and link URLs, emails, and phone numbers without manual span management.
  • Control highlight color via textView.highlightColor to match your app's visual design.
  • Always test that LinkMovementMethod is set when using spans, and be cautious about mixing autoLink with custom spannable text.

Course illustration
Course illustration

All Rights Reserved.