I have set specific words in a string clickable, and although the functionality is working, the text always highlights a blue color until you press outside of the clickable text onto non-clickable text. Also note that inflating views or pressing any other buttons will keep the text highlighted too. It seems that you have to click on the non-clickable text area to get rid of the highlighted clickable text. How can I prevent the text from highlighting after I click on my clickable selected words? Here is my setup
SpannableString ss = new SpannableString(Html.fromHtml(getActivity().getApplicationContext().getResources().getString(R.string.my_string)));
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
Logger.i(TAG, "clicked on clickable words");
}
};
// makes the words clickable
ss.setSpan(clickableSpan, 10, 23, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// makes the clickable words remain red link instead of blue
ss.setSpan(new ForegroundColorSpan(getActivity().getApplicationContext().getResources().getColor(R.color.red)), 30, 43, 0);
tv.setText(ss);
tv.setMovementMethod(LinkMovementMethod.getInstance());
Anyone have any ideas for this? Thanks in advance!
I found the answer, tv.setHighlightColor(Color.TRANSPARENT) works. And is the easiest solution compared to overriding ClickableSpan and trying to do something like
import android.graphics.Color;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.View;
public class WordSpan extends ClickableSpan
{
private int id;
private TextPaint textpaint;
public boolean shouldHilightWord = false;
public WordSpan(int anID, String txt, int selected) {
id =anID;
// if the word selected is the same as the ID set the highlight flag
if(selected == id) {
shouldHilightWord = true;
}
}
#Override
public void updateDrawState(TextPaint ds) {
textpaint = ds;
ds.setColor(ds.linkColor);
if(shouldHilightWord){
textpaint.bgColor = Color.GRAY;
textpaint.setARGB(255, 255, 255, 255);
}
//Remove default underline associated with spans
ds.setUnderlineText(false);
}
public void changeSpanBgColor(View widget){
shouldHilightWord = true;
updateDrawState(textpaint);
widget.invalidate();
}
#Override
public void onClick(View widget) {
// TODO Auto-generated method stub
}
/**
* This function sets the span to record the word number, as the span ID
* #param spanID
*/
public void setSpanTextID(int spanID){
id = spanID;
}
/**
* Return the wordId of this span
* #return id
*/
public int getSpanTextID(){
return id;
}
}
Hopefully this answer will save someone a lot of work!
Try the below code to remove all color spans from Spannable string :
ForegroundColorSpan[] colorSpans = ss.getSpans(0, ss.length(), ForegroundColorSpan.class);
for(ForegroundColorSpan colorSpan : colorSpans){
ss.removeSpan(colorSpan);
}
Related
I am using a text view in my aap, which is having plane text as well as a hyperlink. Now when I click on hyperlink then link open with default browser. But in actual I dont want to open default browser. Actually I want to register OnClickListener on hyperlink and want to perform other.
I searched on internet and I got this solution...
Control onclicklistener in autolink enabled textview
But this is not helpful for me.
Anyone can tell me that how I can perform this.
Thanks in advance
you can use a Spannable object
final Spannable span = new SpannableString(text);
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
}
}, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
where text is your hyperlink
Remove android:autoLink="web" if this property setted into XML.
TextView textView =(TextView)findViewById(R.id.textView);
textView.setClickable(true);
when you want to open in browser use this code
textView.setMovementMethod(LinkMovementMethod.getInstance());
String text = "<a href='http://www.google.com'> Google </a>";
textView.setText(Html.fromHtml(text));
if you want to perform some operation register onclick listener for textview and perform.
textView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
Try doing this add
in your
main.xml
<TextView
android:id="#+id/yourTVID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="performSomeAction" />
in your SomeActivity.java
public void performSomeAction( View v){
//Perform your action
}
Try this, it should solve your problem. This method will return a Spannable String which have part of it clickable.
Before calling the below method you should Create CharSequence from the String then convert it to Spannable
CharSequence charSequencce = testView.getText();
Spannable spannable = (Spannable) charSequencce;
public SpannableStringBuilder addClickToPartsOfString(Spannable charSequence, String[] stringsToAddClick, final OnHyperLinkClickListener onClickListener) {
SpannableStringBuilder ssb = new SpannableStringBuilder(charSequence);
for(final String s : stringsToAddClick) {
int index1 = charSequence.toString().indexOf(s);
int index2 = (s.length() + index1);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
onClickListener.onClick(s);
}
}, index1, index2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return ssb;
}
I've just made a library aiming to simplify this. See Textoo. You can achieve the same with code like:
TextView locNotFound = Textoo
.config((TextView) findViewById(R.id.view_location_disabled))
.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();
Internally the library converts existing links in your textview / string resources (android system parse html links in string resources into Span for you already) into custom ClickableSpan and capture clicks into calls to your handlers.
This relieve you from having to calculate and hard coding the position of clickable spans to add. Thus make it easier to externalize your text into string resources and better for localization.
nickname is floating over comment body text.
It looks like css float effect.
I want to make layout this.
nickname has color, and clickable, and comment text are floating by nickname.
how can I do this for android?
hey i have implemented in my code using SpannableString
SpannableString spannableString = new SpannableString("userName");
final String tag = tagString.substring(start, i);
spannableString.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
if (tag.equals("username")) {
}
}
#Override
public void updateDrawState(TextPaint ds) {
}
}, 0, username.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
I Want to create mulitple TextView dynamically in ListView item. suppose i use LinearLayout it will create textview horizontal or vertically. I want multiple textview with the wraping. How can i create like that please share your valuable ideas,
Below screen images.
Note :
Each textview have the click action
Mike voted 8 , lara voted 9 like that individual text with wraping conetxt.
I have a custom view (merge xml) that contains a text view (originally it's a more complicated view).
My custom view class like this
public class Example extends LinearLayout {
protected Context context;
protected TextView titleView;
public Example(Context context) {
super(context);
this.context = context;
LayoutInflater inflater = (LayoutInflater) `enter code here`context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.bloghu_title_layout, this, true);
this.setOrientation(LinearLayout.VERTICAL);
titleView = (TextView) getChildAt(0);
}
public void setBlogTitle(String blogTitle, final String blogUrl, String author, final String authorUrl) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append(blogTitle.toUpperCase());
spannableStringBuilder.append(" / ");
spannableStringBuilder.setSpan(new RelativeSizeSpan(1.5f), 0, blogTitle.length() + 2, 0);
spannableStringBuilder.append(author);
spannableStringBuilder.setSpan(new RelativeSizeSpan(1.2f), spannableStringBuilder.length() - author.length(), spannableStringBuilder.length(), 0);
spannableStringBuilder.setSpan(new NonUnderlineClickableSpan() {
#Override
public void onClick(View widget) {
Log.d("span", blogUrl);
}
}, 0, blogTitle.length(), 0);
spannableStringBuilder.setSpan(new NonUnderlineClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(context, authorUrl, Toast.LENGTH_SHORT).show();
}
}, spannableStringBuilder.length() - author.length(), spannableStringBuilder.length(), 0);
spannableStringBuilder.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.index_orange)), 0, blogTitle.length(), 0);
spannableStringBuilder.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.black)),
spannableStringBuilder.length() - author.length(), spannableStringBuilder.length(), 0);
titleView.setMovementMethod(LinkMovementMethod.getInstance());
titleView.setText(spannableStringBuilder, BufferType.SPANNABLE);
}
}
The NonUnderlineClickableSpan() is an extended ClickAbleSpan(), it just because I don't want to underline the clickable text, end it has an empty onclick method that you have to override:
public class NonUnderlineClickableSpan extends ClickableSpan{
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(false); // set to false to remove underline
}
#Override
public void onClick(View widget) {
// TODO Auto-generated method stub
}
As you can see in Example class you can set a new NonUnderlineClickableSpan, in its' onClick() method you can set what to happen, than you have to set the first and the last character of the clickable span, and a flag (this is the last parameter, in this case 0).
Whit ForegroundSpan you can set font color, whith relative size span you can set different text sizes, and there are a lot of span to style your text and make it interactive, but it is a very under-documented part of android.
I haven't found a good tutorial about this topic yet, so if somebody know one, pls let me know :).
What is the problem, whit textviews in linearLayout? But I think, what you really looking for is spannable string,in this case you can set the formats (colour, font size, style and what ever you want, and onClick actions for every word, and you need just one text view.
How to change text color of a link when pressed(Touch or pressed effect). Please see my code below
Code:
SpannableString spanStr = new SpannableString(tag);
spanStr.setSpan(new HashTagsClickableSpan(tag), 0, tag.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanStr.setSpan(new ForegroundColorSpan(Color.RED),0,tag.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
class HashTagsClickableSpan extends ClickableSpan{
String clicked;
public HashTagsClickableSpan(String string) {
super();
clicked =string;
}
public void onClick(View tv) {
Toast.makeText(getActivity(), "Text = " + clicked,Toast.LENGTH_SHORT).show();
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
}
ClickableSpan.onClick is only called after the ACTION_UP, so it's probably too late for the effect you want. In general, you can call View.invalidate() to issue a redraw (and another call to updateDrawState).
To get a nice pressed effect, you're probably better off registering a touch listener with View.setOnTouchListener , listening for the mouse events directly, modifying your custom span state if necessary, and posting an invalidate.
I've been using the android:autoLink just fine for formatting links and such, but I need to use android:onClick so I can't use that in this case. The reasoning is that I find it too easy to click on a phone number accidentally, so I'm going to intercept the click with a confirmation Dialog and then call.
Is there an easy way to still make the phone number in my TextView look like a normal clickable link? I poked around the Android source code, but couldn't find any particular style for me to reference.
This is the shortest solution:
final CharSequence text = tv.getText();
final SpannableString spannableString = new SpannableString( text );
spannableString.setSpan(new URLSpan(""), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(spannableString, TextView.BufferType.SPANNABLE);
Sadly, the effect of clicking doesn't show up as being clicked on a real url link, but you can overcome it like so:
final CharSequence text = tv.getText();
final SpannableString notClickedString = new SpannableString(text);
notClickedString.setSpan(new URLSpan(""), 0, notClickedString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
final SpannableString clickedString = new SpannableString(notClickedString);
clickedString.setSpan(new BackgroundColorSpan(Color.GRAY), 0, notClickedString.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
tv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
tv.setText(clickedString);
break;
case MotionEvent.ACTION_UP:
tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
v.performClick();
break;
case MotionEvent.ACTION_CANCEL:
tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
break;
}
return true;
}
});
Another solution is to use Html.fromHtml(...) , where the text inside has links tags ("") .
If you wish for another solution, check this post.
You can create a colors.xml resource file, what contains colors. Please take a look at Colors
If you want to underline your text, then please take a look at this post:
Underline
Don't forget to add android:clickable="true" or setClickable(true) to
your TextViews to make them clickable!
Linkify is a great class, it hunts for complex patterns like URLs, phone numbers, etc and turns them into URLSpans. Rather than re-write the existing regular expressions I extended the URLSpan class and created a method to upgrade only the telephone URLSpans to a custom URLSpan with a confirmation dialog.
First my extended URLSpan class, ConfirmSpan:
class ConfirmSpan extends URLSpan {
AlertDialog dialog;
View mView;
public ConfirmSpan(URLSpan span) {
super(span.getURL());
}
#Override
public void onClick(View widget) {
mView = widget;
if(dialog == null) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(widget.getContext());
mBuilder.setMessage("Do you want to call: " + getURL().substring(4) + "?");
mBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
openURL();
}
});
dialog = mBuilder.create();
}
dialog.show();
}
public void openURL() {
super.onClick(mView);
}
}
Next the method to swap out the different span classes:
private void swapSpans(TextView textView) {
Spannable spannable = (Spannable) textView.getText();
URLSpan[] spans = textView.getUrls();
for(URLSpan span : spans) {
if(span.getURL().toString().startsWith("tel:")) {
spannable.setSpan(new ConfirmSpan(span), spannable.getSpanStart(span), spannable.getSpanEnd(span), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.removeSpan(span);
}
}
}
Finally all you need to do is create a TextView with the autoLink attribute:
android:autoLink="phone"
And remember to call the swapSpans() method. Understand that I wrote this for fun, there may be other methods of doing this but I am unaware of them at the moment. Hope this helps!
To underline your TextView's text, you have to do something like:
final TextView text = (TextView) findViewById(R.id.text);
SpannableString string = new SpannableString("This is the uderlined text.");
string.setSpan(new UnderlineSpan(), 0, string.length(), 0);
text.setText(string);
This should work. Let me know about your progress.
With kotlin extension function (if you don't need the click effect as on a real link)
fun TextView.hyperlinkStyle() {
setText(
SpannableString(text).apply {
setSpan(
URLSpan(""),
0,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
},
TextView.BufferType.SPANNABLE
)
}
How to use
yourTextView.hyperlinkStyle()
Have a better answer.This is what i did.
final SpannableString ss = new SpannableString("Click here to verify Benificiary");
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
ss.setSpan(clickableSpan,0,ss.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.BLUE);
You go anywhere you like when user clicks on the link through onclick method of ClickableSpan
Simply underline it:
val myText = "Text to be underlined"
textView.text = Html.fromHtml("<u>$myText</u>")
or with kotlin extensions:
fun TextView.underline() {
text = Html.fromHtml("<u>${text}</u>")
}
usage:
textView.text = myText
textView.underline()
More ways to style text in android here: https://medium.com/androiddevelopers/spantastic-text-styling-with-spans-17b0c16b4568