一、需求
1、在TextView中识别url;
2、能识别出非http://|https://|ftp://等协议开头的非标准url
3、对url设置颜色、下划线、点击等等
二、方案
LinkedList mStringList = new LinkedList();
LinkedList mUrlInfos = new LinkedList();
private String pattern =
"((http|ftp|https)://)(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?|(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?";
Pattern r = Pattern.compile(pattern);
Matcher m;
int flag= Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
class UrlInfo {
public int start;
public int end;
}
public SpannableStringBuilderForAllvers identifyUrl(CharSequence text) {
mStringList.clear();
mUrlInfos.clear();
CharSequence contextText;
CharSequence clickText;
text = text == null ? "" : text;
//以下用于拼接本来存在的spanText
SpannableStringBuilderForAllvers span = new SpannableStringBuilderForAllvers(text);
ClickableSpan[] clickableSpans = span.getSpans(0, text.length(), ClickableSpan.class);
if (clickableSpans.length > 0) {
int start=0;
int end=0;
for (int i=0;i
start=span.getSpanStart(clickableSpans[0]);
end=span.getSpanEnd(clickableSpans[i]);
}
//可点击文本后面的内容页
contextText = text.subSequence(end, text.length());
//可点击文本
clickText = text.subSequence(start,
end);
} else {
contextText = text;
clickText = null;
}
m = r.matcher(contextText);
//匹配成功
while (m.find()) {
//得到网址数
UrlInfo info = new UrlInfo();
info.start = m.start();
info.end = m.end();
mStringList.add(m.group());
mUrlInfos.add(info);
}
return joinText(clickText, contextText);
}
/** 拼接文本 */
private SpannableStringBuilderForAllvers joinText(CharSequence clickSpanText,
CharSequence contentText) {
SpannableStringBuilderForAllvers spanBuilder;
if (clickSpanText != null) {
spanBuilder = new SpannableStringBuilderForAllvers(clickSpanText);
} else {
spanBuilder = new SpannableStringBuilderForAllvers();
}
if (mStringList.size() > 0) {
//只有一个网址
if (mStringList.size() == 1) {
String preStr = contentText.toString().substring(0, mUrlInfos.get(0).start);
spanBuilder.append(preStr);
String url = mStringList.get(0);
int start = spanBuilder.length();
spanBuilder.append(url, new UnderlineSpan(), flag);
int end = spanBuilder.length();
if (start >= 0 && end > 0 && end > start) {
spanBuilder.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, flag);
}
String nextStr = contentText.toString().substring(mUrlInfos.get(0).end);
spanBuilder.append(nextStr);
} else {
//有多个网址
for (int i = 0; i < mStringList.size(); i++) {
if (i == 0) {
//拼接第1个span的前面文本
String headStr =
contentText.toString().substring(0, mUrlInfos.get(0).start);
spanBuilder.append(headStr);
}
if (i == mStringList.size() - 1) {
//拼接最后一个span的后面的文本
int start = spanBuilder.length();
spanBuilder.append(mStringList.get(i), new UnderlineSpan(),
flag);
int end = spanBuilder.length();
if (start >= 0 && end > 0 && end > start) {
spanBuilder.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, flag);
}
String footStr = contentText.toString().substring(mUrlInfos.get(i).end);
spanBuilder.append(footStr);
}
if (i != mStringList.size() - 1) {
//拼接两两span之间的文本
int start = spanBuilder.length();
spanBuilder.append(mStringList.get(i), new UnderlineSpan(), flag);
int end = spanBuilder.length();
if (start >= 0 && end > 0 && end > start) {
spanBuilder.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, flag);
}
String betweenStr = contentText.toString()
.substring(mUrlInfos.get(i).end,
mUrlInfos.get(i + 1).start);
spanBuilder.append(betweenStr);
}
}
}
} else {
spanBuilder.append(contentText);
}
return spanBuilder;
}
public class SpannableStringBuilderForAllvers extends SpannableStringBuilder{
public SpannableStringBuilderForAllvers() {
super("");
}
public SpannableStringBuilderForAllvers(CharSequence text) {
super(text, 0, text.length());
}
public SpannableStringBuilderForAllvers(CharSequence text, int start, int end){
super(text,start,end);
}
@Override
public SpannableStringBuilder append(CharSequence text) {
if (text == null) {
return this;
}
int length = length();
return (SpannableStringBuilderForAllvers)replace(length, length, text, 0, text.length());
}
/**该方法在原API里面只支持API21或者以上,这里适应低版本*/
public SpannableStringBuilderForAllvers append(CharSequence text, Object what, int flags) {
if (text == null) {
return this;
}
int start = length();
append(text);
setSpan(what, start, length(), flags);
return this;
}
}
标签:end,spanBuilder,url,text,length,start,int,android,TextView
来源: https://www.cnblogs.com/wangqiong/p/10756752.html