Android: Make a part of TextView's text NOT-clickable at runtime? - android

I used Android.text.style.ClickableSpan to make a part (Black) of a string (Blue | Black) clickable:
SpannableString spannableString = new SpannableString("Blue | Black ");
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
//...
}
};
ss.setSpan(clickableSpan, 7, 11, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView textView = (TextView) findViewById(R.id.secondActivity_textView4);
textView.setText(spannableString);
textView.setMovementMethod(LinkMovementMethod.getInstance());
So Black part of the string is clickable. What I want is that when the user clicks Black, it should make Black Not-clickable, and Blue (another part of the same string) clickable.
So to make Blue clickable, we can call setSpan() on the same spannableString another time. But how can I make Black not-clickable?

You can call removeSpan() to remove any previously added Spans. In this particular case it's very easy, as we hold a reference to the very Span we want to remove:
ClickableSpan clickableSpan = new ClickableSpan()
{
#Override
public void onClick(View view)
{
((SpannableString)textView.getText()).removeSpan(this);
}
};
Another option could be to iterate over all ClickableSpan instances and remove them all, such as:
SpannableString str = (SpannableString)textView.getText();
for (ClickableSpan span : str.getSpans(0, str.length(), ClickableSpan.class))
str.removeSpan(span);
For some reason that I cannot fathom, the documentation for spans is really poor... they are quite powerful!

Related

SpannableStringBuilder not displaying text in Text View

I'm trying to make an array of strings individually clickable within a text view that is within a RecyclerView (each tag would pass different data, which is fetched from the api on load). I've created the string using SpannableStringBuilder as below within the bindView method.
fun bindView(link: PostsModel)
val tags = link.topics
var spans = SpannableStringBuilder()
for (tag in tags) {
val string = SpannableString(tag.name)
string.setSpan(ClickableTags(tag.name), 0, tag.name.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
spans.append(string)
}
}
Then I set it to the text view.
view.headerTags.setText(spans, TextView.BufferType.SPANNABLE)
If I println() the contents of spans and view.headerTags.text, I can see it contains a string of tags, so it seems to be working. However, when testing in the app, it's not appearing in the text view.
If I set view.headerTags.text = "Tags should appear here", it works, so I'm not sure there's a problem with the text view.
Can't see to work out why it wouldn't appear, especially if the console is printing out the contents of text view? Can anyone let me know what I might be missing here?
Please use
Spannable word2 = new SpannableString("By signing in, I agree to The xxxxx\nxxxxxxx Terms of Service and Privacy Policy.");
word2.setSpan(clickableSpan, 44, 60, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
word2.setSpan(clickableSpan1, 65, 80, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(word2);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.TRANSPARENT);
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
Intent intent = new Intent(SignInActivity.this, ReadTermsOfServiceActivity.class);
intent.putExtra("FROM", "termsservices");
startActivity(intent);
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};

Wrap multiple textviews to appear as one sentence

Consider the sentence
"Mike has commented on Davids review at Pizza Planet"
This sentence may wrap onto 2 lines, but I want the words "Mike", "Davids" and "Pizza Planet clickable items".
If I use separate TextViews for each of these word, and also for the non clickable words in between, How can I do this so that they wrap nicely onto 2 lines?
You can use spannable strings for your needs, check this out:
TextView textView = (TextView) findViewById(R.id.textView);
SpannableString user = new SpannableString("Mike");
ClickableSpan userClickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
//click on user
}
};
user.setSpan(userClickableSpan, 0, user.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString commentedOnUser = new SpannableString("Davids");
ClickableSpan commentedOnUserClickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
//click on commentedOnUser
}
};
commentedOnUser.setSpan(commentedOnUserClickableSpan, 0, commentedOnUser.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString place = new SpannableString("Pizza Planet");
ClickableSpan placeClickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
//click on place
}
};
place.setSpan(placeClickableSpan, 0, place.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.TRANSPARENT);
textView.setText(user);
textView.append(" is has commented on ");
textView.append(commentedOnUser);
textView.append(" review at ");
textView.append(place);
Now when it's all part of one TextView, use "\n" to break the line.

The word covered by SpannableStringBuilder in a string gets invisible. How to fix it?

Here's a sample of the code:
String engText = "The story of Sir Walter Raleigh";
TextView textView1 = (TextView) findViewById(R.id.textView1);
textView3.setMovementMethod(LinkMovementMethod.getInstance());
textView3.setText(addClickablePart(engText), BufferType.SPANNABLE);
where
private SpannableStringBuilder addClickablePart(String str)
{
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget)
{
Toast.makeText(getApplicationContext(),"tale",Toast.LENGTH_SHORT).show();
}
}, 4, 9, 0);
return ssb;
}
In this code, when you tap on the word story, a toast pops up saying tale. But here's the problem: In Android of versions 4 and higher, the word story gets invisible, while still you can tap on the blank (invisible) space and the toast pops up without trouble.
How can I keep the word "story" visible or change its color so it stays visible while it will work as a toast when tapped?
I think I've got it myself;
after the first setSpan, I needed to begin immediately with another setSpan which changes the color of the same word. Here it is:
ssb.setSpan(new ForegroundColorSpan(Color.RED), 4, 9,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Android: Prevent changing background color of text in TextView with ClickableSpan when touched

I just want to make some text clickable in TextView, so I used ClickableSpan, but the background color of text is changed when I touched it.
This is my code:
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
// do something
}
};
SpannableString ss = new SpannableString("ClickableSpan Test");
ss.setSpan(clickableSpan, 0, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
How can I prevent changing background color on touch?
Add this in you textview
android:textColorHighlight`="#000000"

Setting clickable string - Textview (Android)

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.

Categories

Resources