Handle Textview Link Click in My Android App

Android TextView with Clickable Links: how to capture clicks?

Based upon another answer, here's a function setTextViewHTML() which parses the links out of a HTML string and makes them clickable, and then lets you respond to the URL.

protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
{
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan clickable = new ClickableSpan() {
public void onClick(View view) {
// Do something with span.getURL() to handle the link click...
}
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
}

protected void setTextViewHTML(TextView text, String html)
{
CharSequence sequence = Html.fromHtml(html);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
for(URLSpan span : urls) {
makeLinkClickable(strBuilder, span);
}
text.setText(strBuilder);
text.setMovementMethod(LinkMovementMethod.getInstance());
}

handle textview link click in my android app

Coming at this almost a year later, there's a different manner in which I solved my particular problem. Since I wanted the link to be handled by my own app, there is a solution that is a bit simpler.

Besides the default intent filter, I simply let my target activity listen to ACTION_VIEW intents, and specifically, those with the scheme com.package.name

<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="com.package.name" />
</intent-filter>

This means that links starting with com.package.name:// will be handled by my activity.

So all I have to do is construct a URL that contains the information I want to convey:

com.package.name://action-to-perform/id-that-might-be-needed/

In my target activity, I can retrieve this address:

Uri data = getIntent().getData();

In my example, I could simply check data for null values, because when ever it isn't null, I'll know it was invoked by means of such a link. From there, I extract the instructions I need from the url to be able to display the appropriate data.

How to make links in a TextView clickable

Buried in the API demos, I found the solution to my problem:

File Link.java:

    // text2 has links specified by putting <a> tags in the string
// resource. By default these links will appear but not
// respond to user input. To make them active, you need to
// call setMovementMethod() on the TextView object.

TextView t2 = (TextView) findViewById(R.id.text2);
t2.setMovementMethod(LinkMovementMethod.getInstance());

I removed most of the attributes on my TextView to match what was in the demo.

<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/txtCredits"/>

That solved it. It is pretty difficult to uncover and fix.

Important: Don't forget to remove autoLink="web" if you are calling setMovementMethod().

Capture http link click event in android textview

public static void setLinkclickEvent(TextView tv, HandleLinkClickInsideTextView clickInterface) {
String text = tv.getText().toString();
String str = "([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])";
Pattern pattern = Pattern.compile(str);
Matcher matcher = pattern.matcher(tv.getText());
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
InternalURLSpan span = new InternalURLSpan();
span.setText(text.substring(x, y));
span.setClickInterface(clickInterface);
f.setSpan(span, x, y,
android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
}
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setFocusable(false);
}

public static class InternalURLSpan extends android.text.style.ClickableSpan {

private String text;
private HandleLinkClickInsideTextView clickInterface;

@Override
public void onClick(View widget) {
getClickInterface().onLinkClicked(getText());
}

public void setText(String textString) {
this.text = textString;
}

public String getText() {
return this.text;
}

public void setClickInterface(HandleLinkClickInsideTextView clickInterface) {
this.clickInterface = clickInterface;
}

public HandleLinkClickInsideTextView getClickInterface() {
return this.clickInterface;
}

}

public interface HandleLinkClickInsideTextView {
public void onLinkClicked(String url);
}

After this i just used the method send click event.

textview.setText("http://google.com is google website and http://youtube.com is youtube site");
setLinkclickEvent(textview, new HandleLinkClickInsideTextView() {
public void onLinkClicked(String url) {
// Here I added my code
}
});

After clicking link in textview, how to open that link in webview instead of default browser?

The following problems need to be solved:

Linkify the TextView
Find a way to listen to a click on a link in the TextView
Get the url of the clicked link and load it in the WebView
Optional: make the TextView clickable without losing the ability to select text
Optional: handle formatted text in the TextView (different text sizes and styles)

1 Linkify the TextView

String text = "These are some sample links:\nwww.google.com\nwww.facebook.com\nwww.yahoo.com";
Spannable spannable = new SpannableString( Html.fromHtml(text) );
Linkify.addLinks(spannable, Linkify.WEB_URLS);

2 + #3 Listen to clicks on links and open them in the WebView

URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
for (URLSpan urlSpan : spans) {
LinkSpan linkSpan = new LinkSpan(urlSpan.getURL());
int spanStart = spannable.getSpanStart(urlSpan);
int spanEnd = spannable.getSpanEnd(urlSpan);
spannable.setSpan(linkSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.removeSpan(urlSpan);
}

For opening in new activity:

 private class LinkSpan extends URLSpan {
private LinkSpan(String url) {
super(url);
}

@Override
public void onClick(View view) {
String url = getURL();
if (url != null) {


startActivity(new Intent(LinkTestActivity.this,WebViewActivity.class).putExtra("url",url));

}
}
}

And loding the url in webview.

for more see below link :-

Open URL in WebView instead of default Browser

How to intercept click on link in TextView?

There's this method: https://stackoverflow.com/a/3452944/1799219

All it's really doing is passing the link to your own activity (as links are normally passed to other activities) and then you extract the URL.

How handle 2 link click in textview use string resources?

I have used as below mentioned in my apps.

string.xml

<string name="about_fragment_privacy_policy" translatable="false">User Agreement and Privacy Policy</string>

Layout.xml

<TextView
android:id="@+id/privacyPolicy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_fragment_privacy_policy" />

Kotlin code

string = getString(R.string.about_fragment_privacy_policy)
spannableString = SpannableString(string)
val clickableUserAgreement = object : ClickableSpan() {
override fun onClick(widget: View) {
startActivity(
Intent(Intent.ACTION_VIEW).setData(
Uri.parse(
"https://example.com"
)
)
)
}
}
val clickablePrivacyPolicy = object : ClickableSpan() {
override fun onClick(widget: View) {
startActivity(
Intent(Intent.ACTION_VIEW).setData(
Uri.parse(
"https://example.com"
)
)
)
}
}
spannableString.setSpan(
clickableUserAgreement,
0,
14,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannableString.setSpan(
ForegroundColorSpan(resources.getColor(R.color.colorPrimary)),
0,
14,
0
)
spannableString.setSpan(
clickablePrivacyPolicy,
19,
string.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannableString.setSpan(
ForegroundColorSpan(resources.getColor(R.color.colorPrimary)),
19,
string.length,
0
)
privacyPolicy.text = spannableString
privacyPolicy.movementMethod = LinkMovementMethod.getInstance()

TextView catch clicking on link when autoLink is set to web

Actually,

I solved this by abandoning autolLink='web' and by parsing html url, creating SpannableString and setting additional spans.

So, let's say that I want to do the following:

  • if user clicks on the part of the text of textView which is not url, method someMethod() should be called
  • if user clicks on the part of the text of textView which is url, method someMethod() should be called and browser should be openned with given URL

So, first we have the content which is in the variable message and method String extractFirstLink(String text) will be used to get the url.

private static String extractFirstLink(String text) {
Matcher m = Patterns.WEB_URL.matcher(text);
return m.find() ? m.group() : null;
}

Note: in my case I know that I will have only one url, but if you can expect more than one url, this solution (found somewhere on StackOverflow, can't find it right now) will do the work:

public static String[] extractLinks(String text) {
List<String> links = new ArrayList<String>();
Matcher m = Patterns.WEB_URL.matcher(text);
while (m.find()) {
String url = m.group();
links.add(url);
}
return links.toArray(new String[links.size()]);
}

So, here is the code:

int contentTextColor = ...; // color of non-url text in textView
int urlTextColor = ...;
String message = notification.getMessage(); // content stored
final String foundLink = extractFirstLink(message);
SpannableString styledString = new SpannableString(message);

if (foundLink != null) {
int startPosition = message.indexOf(foundLink);
int endPosition = startPosition + foundLink.length();
styledString.setSpan(new ForegroundColorSpan(urlTextColor), startPosition, endPosition, 0);

ClickableSpan clickableURLSpan = new ClickableSpan() {
@Override
public void onClick(View widget) {
someMethod();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(foundLink));
widget.getContext().startActivity(browserIntent);
}
};

ClickableSpan clickableNonURLSpan1 = new ClickableSpan() {
@Override
public void onClick(View view) {
someMethod();
}

@Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
};
ClickableSpan clickableNonURLSpan2 = new ClickableSpan() {
@Override
public void onClick(View view) {
someMethod();
}

@Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
};
styledString.setSpan(clickableURLSpan, startPosition, endPosition, 0);
if (startPosition > 0) {
styledString.setSpan(clickableNonURLSpan1, 0, startPosition - 1, 0);
styledString.setSpan(new ForegroundColorSpan(contentTextColor), 0, startPosition -1, 0);
}
if (endPosition < message.length() -1) {
styledString.setSpan(clickableNonURLSpan2, endPosition + 1, message.length(), 0);
styledString.setSpan(new ForegroundColorSpan(contentTextColor), endPosition + 1, message.length(), 0);
}

txtView.setMovementMethod(LinkMovementMethod.getInstance());
}

txtView.setText(styledString);

There are some interesting things here. For example, when I wish to make span responsive to click, I have to use ClickableSpan, but! I must handle situation where I have format text1-url-text2. So, since all these three parts should be ClickableSpans and text1 and text2 should not have underline, which is the default behaviour of it, I had to override updateDrawState method in my implementation of ClickableSpan for text1 and text2.

There is another catch, I had to create two implementation of ClickableSpan interface in order to have to work as intended. That's why I created clickableNonURLSpan1 and clickableNonURLSpan2.



Related Topics



Leave a reply



Submit