I need to enable click action for links in Textview and open the webpage in app window. Linkify will open in browser.But I want to open in a webview in my app. Please help me.
There's a blog post that talks about extending ClickableSpan.
First extending the ClickableSpan class:
static class InternalURLSpan extends ClickableSpan {
OnClickListener mListener;
public InternalURLSpan(OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View widget) {
mListener.onClick(widget);
}
}
The blog talks about the clickable link doing something in your activity. You can easily adapt this approach to open the URL in a WebView.
It would essentially look something like this:
SpannableString ss = new SpannableString("....")
ss.setSpan(new InternalURLSpan(new OnClickListener() {
public void onClick(View v) {
// Your code to open the link in a WebView here.
}
}), x, y, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
You would just set the SpannableString object as the text of your TextView:
textView.setText(ss);
You can underline textview through string.xml file
<string name="hello_world"><u>Hello world!<u></string>
Now you can set onClickListener on your textView and can redirect user to your webView Activity instead of browser app.
Related
I would like to link some text on a TextView to an Activity. This is the TextView that I have:
<TextView
android:id="#+id/termsLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/terms"
android:layout_weight="4"/>
where #string/terms is:
<string name="terms">Accept terms & conditions..</string>
If I had a link to a webpage I would do it like this:
TextView link = (TextView) findViewById(R.id.termsLink);
link.setMovementMethod(LinkMovementMethod.getInstance());
but I do not know how to start an Activity when I press the link as when it is a real link (that it links a webpage).
EDIT: Please note that I do not have to handle the onClick event in the full text because the link is only on the part "terms & conditions".
EDIT 2: I have tried using two TextView as suggested on the comments and one of the answers below to make the same effect. But sometimes (depending on the screen) the "terms & conditions" part occupy two lines because it does not fill properly on the available space so the second line it is shown on the second TextView and not on the begining of the second line.
The effect is similar to this:
Accept terms &
conditions.
and I would like that it would be like this:
Accept terms &
conditions.
Thanks in advance!
Create a helper class with inner onClick listener
public class ClickSpan extends ClickableSpan {
private String url;
private OnClickListener listener;
public ClickSpan(String url, OnClickListener listener) {
this.url = url;
this.listener = listener;
}
#Override
public void onClick(View widget) {
if (listener != null) listener.onClick(url);
}
public interface OnClickListener {
void onClick(String url);
}
}
Then convert existing span into clickable one
public static Spannable createClickableSpans(Spanned original, ClickSpan.OnClickListener listener) {
SpannableString result = new SpannableString(original);
URLSpan[] spans = result.getSpans(0, result.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = result.getSpanStart(span);
int end = result.getSpanEnd(span);
int flags = result.getSpanFlags(span);
result.removeSpan(span);
result.setSpan(new ClickSpan(span.getURL(), listener), start, end, flags);
}
return result;
}
So, final usage would be like
TextView link = (TextView) findViewById(R.id.termsLink);
link.setMovementMethod(LinkMovementMethod.getInstance());
link.setText(createClickableSpans((Spanned)link.getText(), new ClickSpan.OnClickListener(){
#Override
public void onClick(String url){
//Handle URL on text view click
}
}));
To make only part of a TextView clickable, you can use a spannable inside the TextView and set an onClick event listener. From here, you launch the activity with an intent as usual. You can limit the clickable section of the text by specifying the character positions (start to end)
Checkout this answer by #becomputer06
How to set the part of the text view is clickable
You should probably separate the text into 2 text views one with the terms and condition and one with just the accept.It would make things cleaner and easier. The following TextView is assuming its just for accept.
In the layouts corresponding java class(example: activity_main -> MainActivity):
public void start_activity(View view){
Intent newActivityIntent = new Intent(this,NewActivity.class);
startActivity(newActivityIntent);
}
NewActivity.class is just the name of the activity you want to start.
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
....
}
public void start_activity(View view){
.....
}
}
There are a lot of answers about how to enable links in a TextView, but I couldn't find anything about how to make [a portion of] text in a TextView look like a link with a custom action. In other words I want to fake a link because the action isn't important enough to get a button. I don't want it to look like a main action on the page.
For example, in my about dialog I want to show the text "Open Source Licenses", have it look like a link, but launch my OpenSourceLicensesActivity instead of an actual URL.
I eventually got my answer from posts by those who were experiencing issues with the above, so I'm providing an answer to this specific question here.
The method below will make the portion of the text from start to end clickable.
public static void makeClickableLink (#NonNull final TextView textView,
#NonNull final CharSequence text,
final int start,
final int end,
#NonNull final ClickableSpan onClick) {
final SpannableString span = new SpannableString (text);
span.setSpan (onClick, start, end, 0);
textView.setText (span);
textView.setMovementMethod (LinkMovementMethod.getInstance ());
}
The provided ClickableSpan lets you handle the click event as such:
final TextView tv = (TextView)findViewById (android.R.id.text1);
final ClickableSpan link = new ClickableSpan () {
#Override public void onClick (final View widget) {
context.startActivity (new Intent (context, OpenSourceLicensesActivity.class));
}
};
makeClickableLink (tv, "Click here for OSS Licenses", 5, 9, link);
The above should makehere clickable, launching your activity.
i have a TextView filled with text which i get from a server. I'm using Linkify for handling all the link searching and for setting a URLSpan where needed throughout its addLinks method.
The problem is that the default behavior when clicking a link is opening it in a browser, what i want is to get the clicked link and handle it my self.
I don't see any method of Linkify which let me set a "OnClick" or something...
Thank for your help :)
Ok so i finally managed to set my own "OnClickListener" to the TextView's links.
My solution was to copy Linkify to my project, name it CustomLinkify and just change its applyLink method:
From:
private static final void applyLink(String url, int start, int end, Spannable text)
{
URLSpan span = new URLSpan(url);
text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
To:
private static final void applyLink(final String url, int start, int end, Spannable text)
{
URLSpan span = new URLSpan(url)
{
#Override
public void onClick(View widget)
{
_onLinkClickListener.onLinkClicked(url);
}
};
text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
Where _onLinkClickListener is a new field, set by me before using the new CustomLinkify.
I know its not a very elegant solution and i prefered google to allow setting a listener through the native Linkify, but, for me, this is better than implementing my own Spannable logics (as suggested in other related questions).
I trust the Linkify code and i guess i'll check from time to time to see if any changes made on it, if so, i'll of course update CustomLinkify with the changes.
Hope this will help someone.
I also find it tedious to implement custom Spannable logics in app, and end up creating a library for this. See Textoo.
With Textoo, this can be achieve like:
TextView myTextView = Textoo
.config((TextView) findViewById(R.id.my_text_view))
.linkifyEmailAddresses()
.linkifyMapAddresses()
.linkifyPhoneNumbers()
.linkifyWebUrls() // or just .linkifyAll()
.linkify(patternSettings, "internal://settings/")
.linkify(patternGoogle, "http://www.google.ie/search2?q=", null, transformFilter)
.linkify(patternGoogle, "http://www.google.ie/search3?q=", matchFilter, transformFilter)
.addLinksHandler(new LinksHandler() {
#Override
public boolean onClick(View view, String url) {
if ("internal://settings/location".equals(url)) {
Intent locSettings = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(locSettings);
return true;
} else {
return false;
}
}
})
.apply();
Just to share and hope somebody will find it useful.
Maybe you should use a WebView instead of a TextView?
My code looks like this,
String content = "Hi this is #Naveen. I'll meet #Peter in the evening.. Would you like to join #Sam??";
TextView contentTextView=(TextView)userHeader.findViewById(R.id.contentTextView);
contentTextView.setText(content);
Before setting the text in the textview, I would like to add click event for #Naveen, #Peter and #Sam.. When the user taps on these texts I want to open a new intent.. Is that possible? Any pointers would be quite helpful.
You can try to use Linkify with custom patterns.
However, if that doesn't suit your needs you can try this:
SpannableString ss = new SpannableString("Hi this is #Naveen. I'll meet #Peter in the evening.. Would you like to join #Sam??");
ClickableSpan clickableSpanNaveen = new ClickableSpan() {
#Override
public void onClick(View textView) {
//Do Stuff for naveen
}
};
ClickableSpan clickableSpanPeter = new ClickableSpan() {
#Override
public void onClick(View textView) {
//Do Stuff for peter
}
};
ClickableSpan clickableSpanSam = new ClickableSpan() {
#Override
public void onClick(View textView) {
//Do Stuff for sam
}
};
ss.setSpan(clickableSpanNaveen, 11, 17, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(clickableSpanPeter, 29, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(clickableSpanSam, 76, 79, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView contentTextView=(TextView)userHeader.findViewById(R.id.contentTextView);
contentTextView.setText(ss);
contentTextView.setMovementMethod(LinkMovementMethod.getInstance());
You can use the Linkify class, which provides methods for adding links to TextViews. You can use the addLinks(TextView textView, Pattern pattern, String scheme) method, which needs you to specify the TextView, a Pattern for the text you want to match and a custom scheme that will be used to match Activities that can work with this kind of data. The Activity that you want to be opened when clicking on links must declare this scheme in its intent-filter. Hope this helps.
As the title explains, I'd like to add links to my TextView, with these two caveats:
I want the link to act on a part of the TextView, not the full one (something like an A anchor in HTML).
I want the link to point to an action in my code, not a website. I could define a method in my activity, or implement an OnClickListener, and execute that when that specific link is clicked.
So far, I succeeded to turn phone numbers, addresses, web sites and emails into dedicated external links using:
Linkify.addLinks(message, Linkify.ALL);
I'd like something similar for internal links (to my method), with the possibility to define custom ones.
Also, using a web page with internal link and a web view is not really an option, as I already have several complex layouts defined, and having to modify the whole application and concepts would be quite a pain...
Any idea?
EDIT: Kabuko gave me a very good solution, here is exactly how I implemented it:
final TextView descriptionTextView = (TextView) findViewById(R.id.description);
final Spannable span = Spannable.Factory.getInstance().newSpannable("the full text for the view");
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(StartEventActivity.this, "LINK CLICKED", Toast.LENGTH_SHORT).show();
}
}, 1, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 1 and 20 to be replaced with actual index of start and end of the desired link
descriptionTextView.setText(span);
descriptionTextView.setMovementMethod(LinkMovementMethod.getInstance());
If you wanted to actually go to URLs you could use Html.fromHtml, but if you want your own click handlers you can use a ClickableSpan.
In completion of previous post this might help some one
TextView textView = (TextView) getView().findViewById(R.id.textView);
textView.setText(Html.fromHtml(getString(R.string.html_)) , TextView.BufferType.SPANNABLE);
String tmp = ((Spannable) textView.getText()).toString();
String linkText = getString(R.string.html_link);
int index = tmp.indexOf(linkText);
if(index>=0) {
Spannable spannable = (Spannable) textView.getText() ;
spannable.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
try {
/// do what you must
}catch (Exception ex){
handleException(ex);
}
}
}, index, index+getString(R.string.html_link).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}