OSC中超链接有 新闻超链接,@好友超链接,话题超链接等等.
在讲OSC的处理之前,我先大概说下我以前做新浪微博时的处理,看了OSC的处理后,我发现这种处理很不错。。
首先,先说下我之前处理超链接的方法
public static SpannableString Autolink(String txt, final Context con) {
SpannableString spannableString = new SpannableString(txt);
Pattern pattern = Pattern.compile("@([a-zA-Z0-9_\\-\\u4e00-\\u9fa5]+)|"
+ "#([^\\#|.]+)#" + "|http://t\\.cn/\\w|" + "\\[(\\S+?)\\]");
Matcher matcher = pattern.matcher(txt);
while (matcher.find()) {
final String group = matcher.group();
if (group.startsWith("@")) {
spannableString.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(con, group, Toast.LENGTH_SHORT).show();
Intent in = new Intent(con, HomeActivity.class);
in.putExtra("username", group.substring(1));
con.startActivity(in);
}
}, matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ForegroundColorSpan(0xff0077ff),
matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (group.startsWith("#")) {
spannableString.setSpan(new ForegroundColorSpan(0xff0077ff),
matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (group.startsWith("#")) {
} else if (group.startsWith("[")) {
Bitmap b = MyApplication.getInstence().getEmotion(group);
spannableString.setSpan(new ImageSpan(con,b), matcher.start(),
matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (group.startsWith("http://")) {
}
}
return spannableString;
}
首先定义一个正则表达式,根据开头的字符进行不同的处理 ,接下来如何使用呢?
holder.tvItemContent.setText(TextUtil.Autolink((String) getData(position, "text"), mContext));
很简单,但是,我们会发现一个问题,那就是点击listview的item只会响应那个超链接其他所有都不能响应了,当时使用了其他方法处理,下面OSC用了另外一种方法,非常不错。
下面主要说说OSC的处理,OSC是通过重写一个TextView实现的
public class LinkView extends TextView {
private OnLinkClickListener mLinkClickListener = new LinkView.OnLinkClickListener() {
@Override
public void onLinkClick() {
}
};
public LinkView(Context context) {
super(context);
}
public LinkView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LinkView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public OnLinkClickListener getLinkClickListener() {
return mLinkClickListener;
}
public void setLinkClickListener(OnLinkClickListener linkClickListener) {
this.mLinkClickListener = linkClickListener;
}
public void setLinkText(String linktxt) {
Spanned span = Html.fromHtml(linktxt);
setText(span);
setMovementMethod(LinkMovementMethod.getInstance());
parseLinkText(span);
}
public void parseLinkText(Spanned spanhtml) {
CharSequence text = getText();
if (text instanceof Spannable) {
int end = text.length();
Spannable sp = (Spannable) getText();
URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
URLSpan[] htmlurls = spanhtml != null ? spanhtml.getSpans(0, end,
URLSpan.class) : new URLSpan[] {};
if (urls.length == 0 && htmlurls.length == 0)
return;
SpannableStringBuilder style = new SpannableStringBuilder(text);
for (URLSpan url : urls) {
if (!isNormalUrl(url)) {
style.removeSpan(url);// 只需要移除之前的URL样式,再重新设置
NoLinkSpan span = new NoLinkSpan(url.getURL());
style.setSpan(span, sp.getSpanStart(url),
sp.getSpanEnd(url),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
continue;
}
style.removeSpan(url);// 只需要移除之前的URL样式,再重新设置
MyURLSpan myURLSpan = new MyURLSpan(url.getURL());
style.setSpan(myURLSpan, sp.getSpanStart(url),
sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (URLSpan url : htmlurls) {
style.removeSpan(url);// 只需要移除之前的URL样式,再重新设置
MyURLSpan myURLSpan = new MyURLSpan(url.getURL());
style.setSpan(myURLSpan, spanhtml.getSpanStart(url),
spanhtml.getSpanEnd(url),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(style);
}
}
public void parseLinkText() {
parseLinkText(null);
}
public class MyURLSpan extends ClickableSpan {
private String mUrl;
public MyURLSpan(String url) {
mUrl = url;
}
@Override
public void onClick(View widget) {
mLinkClickListener.onLinkClick();
URLs urls = URLs.parseURL(mUrl);
if (urls != null) {
UIHelper.showLinkRedirect(widget.getContext(),
urls.getObjType(), urls.getObjId(), urls.getObjKey());
} else {
UIHelper.openBrowser(widget.getContext(), mUrl);
}
}
}
/**
* 无响应的ClickableSpan
*
* @author yeguozhong@yeah.net
*
*/
public class NoLinkSpan extends ClickableSpan {
private String text;
public NoLinkSpan(String text) {
super();
this.text = text;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLACK);
ds.setUnderlineText(false); // 去掉下划线
}
@Override
public void onClick(View widget) {
// doNothing...
}
}
public interface OnLinkClickListener {
void onLinkClick();
}
/**
* 过滤掉一些不正常的链接
*
* @param url
* @return
*/
public boolean isNormalUrl(URLSpan url) {
String urlStr = url.getURL();
if (urlStr.endsWith(".sh")) {
return false;
}
return true;
}
}
parseLinkText这个方法就是找到Html中的URl样式并设置自定义的ClickableSpan,这个主要调用了showLinkRedirect,我们上一篇文章已经说过了 ;setLinkText就是设置超链接的方法,首先会使用fromHtml拿出对应的Span然后设置Text然后解析这个Text。自定义TextView说完了,接下来就看看怎么使用它。
listItemView.content.setLinkText(tweet.getBody());
listItemView.content.setTag(tweet);// 设置隐藏参数(实体类)
listItemView.content.setOnClickListener(linkViewClickListener);
listItemView.content.setLinkClickListener(linkClickListener);
我们发现,这里设置了两个监听器setOnClickListener和setLinkClickListener,这是因为我们点击了超链接后其实是有两个操作的,一个是点击超链接的处理,一个是点击超链接之外的处理。如果不这样处理的话,那么就会出现上面说的不能响应其他事件。接下来我们再看看这两个监听器
private View.OnClickListener linkViewClickListener = new View.OnClickListener() {
public void onClick(View v) {
if (!isLinkViewClick()) {
UIHelper.showTweetDetail(v.getContext(),
((Tweet) v.getTag()).getId());
}
setLinkViewClick(false);
}
};
private OnLinkClickListener linkClickListener = new OnLinkClickListener() {
public void onLinkClick() {
setLinkViewClick(true);
}
};
这里只是设置了一个标志位
public abstract class MyBaseAdapter extends BaseAdapter {
//标识LinkView上的链接
private boolean isLinkViewClick = false;
public boolean isLinkViewClick() {
return isLinkViewClick;
}
public void setLinkViewClick(boolean isLinkViewClick) {
this.isLinkViewClick = isLinkViewClick;
}
}