问题
In my android app's textview, I want to ellipsis all URLs (which already have been linked using clickable span) to get ellipsis (or truncate) if the length of URL is greater than a certain limit.
This behaviour is inspired from twitter and facebook.
For example, the link http://www.getfluttr.com/flap/3rL7/now-only-if-modi-would-listen-to-opposition-party-/ it should look something like this:
(Screenshot Source: Twitter)
I understand that this has to involve spans. I can't seem to be able to find a span that'll allow me to replace text while keeping link.
回答1:
the following code will do the trick for you
public class LinkShortener {
public static final int MAX_LINK_LENGTH = 20;
public static CharSequence shortenLinks(String text) {
return shortenLinks(text, Linkify.ALL);
}
public static CharSequence shortenLinks(String text, int linkMask) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Linkify.addLinks(builder, linkMask);
URLSpan[] spans = builder.getSpans(0, builder.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = builder.getSpanStart(span);
int end = builder.getSpanEnd(span);
int flags = builder.getSpanFlags(span);
CharSequence linkText = builder.subSequence(start, end);
if (linkText.length() > MAX_LINK_LENGTH) {
linkText = linkText.subSequence(0, 20) + "…";
builder.replace(start, end, linkText);
builder.removeSpan(span);
builder.setSpan(span, start, start+linkText.length(), flags);
}
}
return builder;
}
}
Then you can simply use it like this:
itemView.setText(LinkShortener.shortenLinks("https://example.com/really_long_url"));
You might need to disable autoLink on the text view
The code first linkifies the text using the build in Android tooling. Then it goes through all creates URLSpans, and shortens the text via replace. Lastly we change the span to make sure it has the right bounds. Since we are reusing the existing span, the URL will be preserved
回答2:
I added some "pretty" updates to @Filip Wieladek answer based on Twitter behaviour. The provided code first removes the http(s)://www. prefixes providing up to 12 characters for more usefull information. It also perfectly matches the question desired behaviour. Example:
- https://www.stackove... (20 chars)
- stackoverflow.com/que... (20 chars without prefix)
Code
public static CharSequence shortenLinks(String text, int linkMask) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Linkify.addLinks(builder, linkMask);
URLSpan[] spans = builder.getSpans(0, builder.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = builder.getSpanStart(span);
int end = builder.getSpanEnd(span);
int flags = builder.getSpanFlags(span);
CharSequence linkText = builder.subSequence(start, end);
if (linkText.length() > MAX_LINK_LENGTH) {
// 1 - Remove the https:// or http:// prefix
if(linkText.toString().toLowerCase().startsWith("https://"))
linkText = linkText.subSequence("https://".length(), linkText.length());
else if(linkText.toString().toLowerCase().startsWith("http://"))
linkText = linkText.subSequence("http://".length(), linkText.length());
// 2 - Remove the www. prefix
if(linkText.toString().toLowerCase().startsWith("www."))
linkText = linkText.subSequence("www.".length(), linkText.length());
// 3 - Truncate if still longer than MAX_LINK_LENGTH
if (linkText.length() > MAX_LINK_LENGTH) {
linkText = linkText.subSequence(0, MAX_LINK_LENGTH) + "…";
}
// 4 - Replace the text preserving the spans
builder.replace(start, end, linkText);
builder.removeSpan(span);
builder.setSpan(span, start, start+linkText.length(), flags);
}
}
return builder;
}
来源:https://stackoverflow.com/questions/33203359/android-ellipsize-truncate-all-long-urls-in-a-textview