I have a string in database that is like:
string f = "this is the first link and this is the second link"
textview1.TextFormatted = Html.FromHtml(f);
url =?
Intent i = new Intent(Android.Content.Intent.ActionView,url);
StartActivity(i);
the number of links in the string is different. I want to make all link in textview clickable and when user click on each of them, the url of that link send to another activity.
When you setText using Html.fromHtml, the '' are replaced as UrlSpans in textView.
You can get each of url spans and set clickable spans for onClick function.
Refer to this for the solution code.
I have 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:
private void customTextView(TextView view) {
SpannableStringBuilder spanTxt = new SpannableStringBuilder(
getString(R.string.read_and_accept));
spanTxt.setSpan(new ForegroundColorSpan(ContextCompat.getColor(activity, R.color.black_30)), 0,
getString(R.string.read_and_accept).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanTxt.append(" ");
spanTxt.append(getString(R.string.t_and_c));
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Utils.redirectUserToUrl(activity,"http://luxit-driver-terms.tookan.in");
}
}, spanTxt.length() - getString(R.string.t_and_c).length(), spanTxt.length(), 0);
spanTxt.append(" and ");
spanTxt.setSpan(new ForegroundColorSpan(ContextCompat.getColor(activity, R.color.accent)), 48, spanTxt.length(), 0);
spanTxt.append(getString(R.string.privacy_policy));
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Utils.redirectUserToUrl(activity,"http://luxit-driver-privacypolicy.tookan.in/");
}
}, spanTxt.length() - getString(R.string.privacy_policy).length(), spanTxt.length(), 0);
view.setMovementMethod(LinkMovementMethod.getInstance());
view.setText(spanTxt, TextView.BufferType.SPANNABLE);
}
In Xml,use android:textColorLink to add custom color for ur link text
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="text"
android:textColorLink="#000000" />
Related
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);
}
};
I have created 3 strings in string resources. Every string has an external link in it. Basically I am trying to put one sentence in a TextView which has 3 outside links in it. Please tell how to do this in Android.
If we can assign multiple string through XML only that will be best.
If you want to combine your 3 links and make them clickable you can try this :
<string name="combined_links"><![CDATA[ my link one my link two my link three]]></string>
String sentence = getString(R.string.combined_links, getString(R.string.link_one), getString(R.string.link_two), getString(R.string.link_three))
You have to use Spannable, here is example below, have a look
ClickableSpan linkClick = new ClickableSpan() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "Link Click",
Toast.LENGTH_SHORT).show();
view.invalidate();
}
#Override
public void updateDrawState(TextPaint ds) {
if (textView.isPressed()) {
ds.setColor(Color.BLUE);
} else {
ds.setColor(Color.RED);
}
textView.invalidate();
}
};
textView.setHighlightColor(Color.TRANSPARENT);
Spannable spannableString = new SpannableString("Link in TextView");
spannableString.setSpan(linkClick, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString, TextView.BufferType.SPANNABLE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
In this, String Link in TextView only "LINK" is clickable
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 following code shows how I'm applying a pressed state using a custom ClickableSpan and selector. However, the pressed state is applied whenever I press anywhere on the TextView, not just the ClickableSpan. How do I stop this?
Note: it does not call onClick, but does apply state_pressed from the selector. I want it to do neither.
MyView.java
SpannableString spanned = new SpannableString("click here");
spannable.setSpan(new MyClickableSpan() {
#Override
public void onClick(View widget) {
doSomething();
}
}, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spanned);
textView.setMovementMethod(LinkMovementMethod.getInstance());
MyClickableSpan.java
public abstract class MyClickableSpan extends ClickableSpan {
#Override
public abstract void onClick(View view);
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}
the TextView
<TextView
android:id="#+id/my_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textColorLink="#color/my_selector" />
my_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/my_color_pressed" />
<item android:color="#color/my_color" />
</selector>
Edit note: Added TextView code
Next example works as you're expecting:
Spannable span = SpannableStringBuilder.valueOf("Hello clickable span!");
span.setSpan(new MyClickableSpan(), 6, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.setText(span);
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
Now span applied:
Here's MyClickableSpan() that's only show Snackbar to indicate that "click" is handled:
class MyClickableSpan extends ClickableSpan {
#Override
public void onClick(View widget) {
Snackbar.make(getWindow().findViewById(android.R.id.content), "Click on span!", Snackbar.LENGTH_LONG).show();
}
}
We've got:
Click/tap outside the "spanned" text will do nothing
Click/tap on "spanned" part of text will show Snackbar
That's it. Please let me know if you need any additional info.
You have to set MovementMethod to the TextView which has the Span.
textView.setMovementMethod(LinkMovementMethod.getInstance());
You can refer below code I have tested it.
String s = "This is custom string click Here";
SpannableString spanned = new SpannableString(s);
spanned.setSpan(new MyClickableSpan() {
#Override
public void onClick(View widget) {
Log.i("main", "Link clicked");
}
}, s.length() - 10, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spanned);
textView.setMovementMethod(LinkMovementMethod.getInstance());
TextView
<TextView
android:id="#+id/my_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#drawable/my_selector"
android:textColorLink="#color/colorPrimary" />
You can use tutorial here
In your code you have define
android:textColor="#android:color/white"
instead of this you have to define your selector like below
android:textColor="#drawable/my_selector"
rest of code is as it is you have to changed only one line that android:textColor="#drawable/my_selector" that i explain above.
You can do this way:
TextView textView = (TextView)findViewById(R.id.textView);
Spannable span = Spannable.Factory.getInstance().newSpannable("test link span");
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
Log.i("main", "Link clicked");
Toast.makeText(HomeScreenActivity.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set the "test " spannable.
span.setSpan(cs, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set the " span" spannable
span.setSpan(cs, 6, span.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(span);
textView.setMovementMethod(LinkMovementMethod.getInstance());
Hope this will help you.
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.