Android ClickableSpan get text onClick() - android

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!

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

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")

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

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.

Related

Capture http link click event in android textview

I have a link in android textview. I am not able to capture the link click event.
String text = "http:://www.google.com is a google link";
textview.setText(text);
"http:://www.google.com" this span of string is clickable in textview. I want to capture that particular click event.
I tried the following.
public static void setTextView(TextView text, CharSequence sequence) {
UoloLogger.i(TAG, "Setting string :: "+sequence);
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());
}
public static 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) {
UoloLogger.i(TAG, span.getURL());
}
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
}
I started setting text into my textview using setTextView() method. I am getting URLSpan array is empty even if i am having the links.
String text = "http:://www.google.com is a google link";
setTextView(textView, text);
Sorry for the bad english. I think, i have explained my problem. Can someone help me.
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
}
});
You can achieved the same using SpannableStringBuilder.
Simply initialize the TextView that you want to add 2 or more listeners and then pass that to the following method that I have created:
SAMPLE CODE:
private void customTextView(TextView view) {
SpannableStringBuilder spanTxt = new SpannableStringBuilder(
"I agree to the ");
spanTxt.append("Term of services");
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Terms of services Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - "Term of services".length(), spanTxt.length(), 0);
spanTxt.append(" and");
spanTxt.setSpan(new ForegroundColorSpan(Color.BLACK), 32, spanTxt.length(), 0);
spanTxt.append(" Privacy Policy");
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Privacy Policy Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - " Privacy Policy".length(), spanTxt.length(), 0);
view.setMovementMethod(LinkMovementMethod.getInstance());
view.setText(spanTxt, BufferType.SPANNABLE);
}
And in your XML, use android:textColorLink to add custom link color of your choice. Like this:
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColorLink="#C36241" />
If you want to open a link after textview click, there are two options:
Using java code:
Spanned text = Html.fromHtml("<u>GOOGLE.COM</u>");
textView.setText(text);
Uri uri = Uri.parse("http://shopwhere.com.au/");
Intent webIntent = new Intent(Intent.ACTION_VIEW,uri);
// Create and start the chooser
Intent chooser = Intent.createChooser(webIntent, "Open with");
startActivityForResult(chooser,0);
Using XML:
Use android:autoLink="web" inside textview tag. You can also change link color android:textColorHighlight="#android:color/transparent" and android:textColorLink="#color/white".

How to set multiple click on textview android

I want to set multiple click on textview. I see many answers but any answer can't help me. I make spanned string using this code:-
private SpannableStringBuilder addClickablePart(String str) {
SpannableStringBuilder ssb = new SpannableStringBuilder(Html.fromHtml(deafultSpna + feelingSpan+tagfriendspan));
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(AddPostActivity.this, "hello click",
Toast.LENGTH_SHORT).show();
}
}, 0, Html.fromHtml(deafultSpna).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(AddPostActivity.this, "hello click ffff",
Toast.LENGTH_SHORT).show();
}
}, Html.fromHtml(deafultSpna).length(), Html.fromHtml(deafultSpna+feelingSpan).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(AddPostActivity.this, "hello click ffff fdsfds",
Toast.LENGTH_SHORT).show();
}
}, Html.fromHtml(deafultSpna+feelingSpan).length(), Html.fromHtml(deafultSpna+feelingSpan+tagfriendspan).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return ssb;
}
but using this code I found like this view:-
But I want to like this:-
I make spanned using this codefeelingSpan = "<font color=#414141> - Feeling </font><font color=#bd2436>" + feeling_name + "</font>";
Any one can help me so solve this problem. Thanks in advance.
To make things easier, we can start by defining a small class that will make the clickable spans red and show the appropriate message when clicked.
private class MyClickableSpan extends ClickableSpan {
String text;
MyClickableSpan(String text) {
this.text = text;
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false); // get rid of underlining
ds.setColor(Color.RED); // make links red
}
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), text, Toast.LENGTH_SHORT).show();
}
}
Next, we can add a small convenience method to create the clickable spans.
private void addClickableText(SpannableStringBuilder ssb, int startPos, String clickableText, String toastText) {
ssb.append(clickableText);
ssb.setSpan(new MyClickableSpan(toastText), startPos, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
Finally, we can fill the spannable string and display it.
TextView text = findViewById(R.id.text);
SpannableStringBuilder ssb = new SpannableStringBuilder("");
addClickableText(ssb, ssb.length(), "Abhishek Nagar", "hello click");
ssb.append(" - Feeling ");
addClickableText(ssb, ssb.length(), "Sad", "hello click ffff");
ssb.append(" with ");
addClickableText(ssb, ssb.length(), "Anand Jainb", "hello click ffff fdsfds");
text.setMovementMethod(LinkMovementMethod.getInstance()); // make our spans selectable
text.setText(ssb);
And that's all there is to it!
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.txt1);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(addClickablePart(getString(R.string.amanda_bio2)));
}
private SpannableStringBuilder addClickablePart(String str) {
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, "span clicked 1", Toast.LENGTH_LONG).show();
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.RED);
}
}, 200, 214, 0);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, "span clicked 2", Toast.LENGTH_LONG).show();
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLUE);
}
}, 241, 255, 0);
return ssb;
}
}
You can even add multiple spans and also customize its colors.
I Have Created a generalized function for this purpose hope this helps
fun TextView.makeLinks(vararg links: Triple<String, View.OnClickListener,LinkProperties>) {
try {
val spannableString = SpannableString(this.text)
for (link in links) {
val clickableSpan = object : ClickableSpan() {
override fun updateDrawState(textPaint: TextPaint) {
super.updateDrawState(textPaint)
textPaint.isUnderlineText = link.third.isUnderlineText
textPaint.isFakeBoldText = link.third.isBoldText
textPaint.color = link.third.color ?: Color.parseColor(DCColorPicker.BLACK)
}
override fun onClick(view: View) {
Selection.setSelection((view as TextView).text as Spannable, 0)
view.invalidate()
link.second.onClick(view)
}
}
val startIndexOfLink = this.text.toString().indexOf(link.first)
spannableString.setSpan(
clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
this.movementMethod = LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
this.setText(spannableString, TextView.BufferType.SPANNABLE)
} catch (e: Exception) {
Log.e(TAG, "makeLinks: " + e.message)
}
}
and you can add N no. of properties here
data class LinkProperties(val isUnderlineText: Boolean = false, val isBoldText: Boolean = false, val color: Int?=null)
and for calling you can use this function like this
val linkBoldOnly = LinkProperties(isBoldText = true)
val linkBoldUnderline = LinkProperties(isUnderlineText = true, isBoldText = true)
binding.name.makeLinks(
Triple("text", View.OnClickListener { openMore() }, linkBoldUnderline),
Triple(name.toString(), View.OnClickListener { itemClick() }, linkBoldOnly)
)

Set clicklistener on specific part of spannable textview in android

I am having a difficulty in setting a ClickListener in specific part of Text in SpannableTextView in android.
I have this text:
By registering you agree to the Terms And Services
I want to set clicklistener to the bold part only? Is it possible?
Yes, it's possible.
private void prepareTerms(){
String termsAndConditionsText = ...;
String discoverTermsText = ...;
SpannableString ss = new SpannableString(discoverTermsText);
int index = discoverTermsText.indexOf(termsAndConditionsText);
ss.setSpan(
new ClickableSpan() {
#Override
public void onClick(View widget) {
// open a webview here if you want
}
},
index,
index + termsAndConditionsText.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
);
mTermAndCondTextView.setText(ss);
mTermAndCondTextView.setMovementMethod(LinkMovementMethod.getInstance());
}
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
// click function
}
}, start_index, end_index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(builder);
Try this code :
String text1 = "By registering you agree to the" + " ";
String text2 = "Terms And Services";
SpannableString spannableString = new SpannableString(text1 + text2);
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View view) {
// listen click here
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(true);
ds.setColor(Color.BLACK);
}
};
spannableString.setSpan(clickableSpan, text1.length(), text1.length() + text2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(spannableString);
textview.setMovementMethod(LinkMovementMethod.getInstance());
textview.setHighlightColor(Color.BLACK);
You can use the method setSpan from the class android.text.Spannable
Complete example and necessary information provided in the official documentation
In your string "By registering you agree to the Terms And Services" start value would be 35 and end would be stringObj.length

How can I make several clickable parts of text in TextView

How can I make several clickable parts of text in TextView. Every clickable part must have his own action.
you can use android.text.style.ClickableSpan
SpannableString ss = new SpannableString("Hello World");
ClickableSpan span1 = new ClickableSpan() {
#Override
public void onClick(View textView) {
// do some thing
}
};
ClickableSpan span2 = new ClickableSpan() {
#Override
public void onClick(View textView) {
// do another thing
}
};
ss.setSpan(span1, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(span2, 6, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
I store main text and clickable words in different resources.
Strings in resources does not exist for some configurations.
String[] links = new String[3];
links[0] = cntx.getString(cntx.getResources().getIdentifier("footerLink1", "string", cntx.getPackageName()));
links[1] = cntx.getString(cntx.getResources().getIdentifier("footerLink2", "string", cntx.getPackageName()));
links[2] = cntx.getString(cntx.getResources().getIdentifier("footerLink3", "string", cntx.getPackageName()));
String text = String.format(cntx.getString(cntx.getResources().getIdentifier("footerDisclaimer", "string", cntx.getPackageName())), links[0], links[1], links[2]);
SpannableString ss = new SpannableString(text);
setSpanOnLink(ss, links[0], new ClickableSpan() {
#Override
public void onClick(View textView) {
Log.i("Disclaimer Footer", "1 click");
//TODO run item
}
});
setSpanOnLink(ss, links[1], new ClickableSpan() {
#Override
public void onClick(View textView) {
Log.i("Disclaimer Footer", "2 click");
//TODO run item
}
});
setSpanOnLink(ss, links[2], new ClickableSpan() {
#Override
public void onClick(View textView) {
Log.i("Disclaimer Footer", "3click");
//TODO run item
}
});
TextView t1 = new TextView(cntx);
t1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 8);
t1.setText(ss);
t1.setMovementMethod(LinkMovementMethod.getInstance());
private void setSpanOnLink(SpannableString ss, String link, ClickableSpan cs) {
String text = ss.toString();
int start = text.indexOf(link);
int end = start + link.length();
ss.setSpan(cs, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
This is working for me :
in xml :
<TextView
android:id="#+id/tv_by_continuing_str"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:textSize="15sp"
tools:text="Test msg 1 2, 3"
android:textColor="#color/translucent_less_white3"
android:textColorLink="#color/white"
android:gravity="center|bottom"
android:layout_above="#+id/btn_privacy_continue" />
In strings.xml
< string name="by_continuing_str2">< ! [ CDATA[By continuing to use this app, you agree to our <a href="https://go.test.com" style="color:gray"/> Privacy Statement </a> and <a href="https://go.test.com" style="color:gray"/>Services Agreement.]]>< / string>
in the activity :
TextView tv_by_continuing = (TextView) findViewById(R.id.tv_by_continuing);
tv_by_continuing.setText(Html.fromHtml(getString(R.string.by_continuing_str2)));
tv_by_continuing.setMovementMethod(LinkMovementMethod.getInstance());

android - How to set the portion of the text is clickable

I have one TextView. In this view I want to make it as some portion of text is clickable. if you click on that text then I want to open WebView.
I did the following way:
textView.setText(Html.fromHtml("I have read and agree to the " +
"<a href='id.web.freelancer.example.TCActivity://Kode'>TERMS AND CONDITIONS</a>"));
textView.setClickable(true);
textView.setMovementMethod(LinkMovementMethod.getInstance());
Here if you click on the TERMS AND CONDITIONS then it opens in the browser but I want to open it in the WebView.
Another way, borrows a bit from Linkify but allows you to customize your handling.
Custom Span Class:
public class ClickSpan extends ClickableSpan {
private OnClickListener mListener;
public ClickSpan(OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View widget) {
if (mListener != null) mListener.onClick();
}
public interface OnClickListener {
void onClick();
}
}
Helper function:
public static void clickify(TextView view, final String clickableText,
final ClickSpan.OnClickListener listener) {
CharSequence text = view.getText();
String string = text.toString();
ClickSpan span = new ClickSpan(listener);
int start = string.indexOf(clickableText);
int end = start + clickableText.length();
if (start == -1) return;
if (text instanceof Spannable) {
((Spannable)text).setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
SpannableString s = SpannableString.valueOf(text);
s.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(s);
}
MovementMethod m = view.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
view.setMovementMethod(LinkMovementMethod.getInstance());
}
}
Usage:
clickify(textView, clickText,new ClickSpan.OnClickListener()
{
#Override
public void onClick() {
// do something
}
});
try this may it works
SpannableString span = new SpannableString(
"Click here to for gmail page.");
span.setSpan(new URLSpan("http://www.gmail.com"), 6, 10,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv = (TextView) findViewById(R.id.text);
tv.setText(span);
tv.setMovementMethod(LinkMovementMethod.getInstance());
change start and end position according to your text size
How do I make links in a TextView clickable?
or u can create a linear layout with horizontal orientation having 2 textviews making second textview clickable..
Why don't you make the textView call on onClick method:
<TextView
...
android:onClick"openWebView"
...
/>
And then just have a method in your activity called:
public void openWebView (View v) {
....
// Do something
}

Categories

Resources