因为项目需求,要在用户发布动态的时候可以打上标签,超链接,还有图片标签,本来不打算写这篇博客,在查阅资料的时候我发现网上的博客都是类似的,大家你抄我,我抄你,抄来抄去,这就是所谓的拿来主义吧,盗版在国内太过泛滥,不多说,切入正题,先来看下我们今天研究的效果图
我研究了下微博和QQ的动态,发现他们的内容描述都有一个共同点——用html写的?,我查了些资料,主要涉及到以下问题:
来看下我们今天要用到的API:
public static Spanned fromHtml (String source)
public static Spanned fromHtml (String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler)
public static String toHtml (Spanned text)
来看看具体的实现
String html = "点击打开我的博客diy_coder
"
+ "这个#搞笑视频#笑死我了,哈哈,快来看看"
+ "@生活如此多娇"
+ "云音乐福利
"
// + ""
+ "";
private static final int TOPIC_TAG = 0;
private static final int AT_USER = 1;
private static final int NORMAL_URL = 2;
private static final int CUSTOM_TAG = 3;
private Context mContext;
private TextView tv_html;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
tv_html = (TextView) findViewById(R.id.tv_html);
tv_html.setText(getClickableHtml(html));
tv_html.setClickable(true);
tv_html.setMovementMethod(LinkMovementMethod.getInstance());
}
private CharSequence getClickableHtml(String html) {
Spanned spannedHtml = Html.fromHtml(html, mImageGetter, new CustomTagHandler());
SpannableStringBuilder clickableHtmlBuilder = new SpannableStringBuilder(spannedHtml);
URLSpan[] urls = clickableHtmlBuilder.getSpans(0, spannedHtml.length(), URLSpan.class);
for (final URLSpan span : urls) {
int start = clickableHtmlBuilder.getSpanStart(span);
int end = clickableHtmlBuilder.getSpanEnd(span);
int flag = clickableHtmlBuilder.getSpanFlags(span);
final String url = span.getURL();
setUpUrl(clickableHtmlBuilder, span, start, end, flag, url);
}
return clickableHtmlBuilder;
}
private void setUpUrl(SpannableStringBuilder clickableHtmlBuilder, URLSpan span, int start, int end, int flag, final String url) {
CustomClickableSpan clickableSpan = null;
if (url.startsWith("@")) {
clickableSpan = new CustomClickableSpan(AT_USER, url);
} else if (url.startsWith("#")) {
clickableSpan = new CustomClickableSpan(TOPIC_TAG, url);
} else if (url.startsWith("http") || url.startsWith("https")) {
clickableSpan = new CustomClickableSpan(NORMAL_URL, url);
}
clickableHtmlBuilder.removeSpan(span);//清除当前span
clickableHtmlBuilder.setSpan(clickableSpan, start, end, flag);
}
//处理点击事件
class CustomClickableSpan extends ClickableSpan {
String text;
int type;
public CustomClickableSpan(int type, String text) {
this.text = text;
this.type = type;
}
@Override
public void updateDrawState(TextPaint ds) {
int color = getResources().getColor(R.color.blue);
ds.setColor(color);//设置点击文字的颜色
ds.setUnderlineText(false); //去掉下划线
}
@Override
public void onClick(View widget) {
//点击事件处理
Intent intent = null;
switch (type) {
case AT_USER://@用户
intent = new Intent(mContext, UserActivity.class);
intent.putExtra("userId", text);
break;
case TOPIC_TAG://#话题#
intent = new Intent(mContext, TopicActivity.class);
intent.putExtra("topic", text);
break;
case NORMAL_URL://网页
intent = new Intent(mContext, WebActivity.class);
intent.putExtra("url", text);
break;
case CUSTOM_TAG://自定义标签
intent = new Intent(mContext, CustomTagActivity.class);
intent.putExtra("tag", text);
break;
}
startActivity(intent);
}
}
//处理自定义标签
class CustomTagHandler implements Html.TagHandler {
private int startIndex = 0;
private int stopIndex = 0;
@Override
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
if (tag.toLowerCase().equals("tag")) {//自定义标签处理
if (opening) {//开始标签
startTag(tag, output, xmlReader);
} else {//结束标签
endTag(tag, output, xmlReader);
}
}
}
public void startTag(String tag, Editable output, XMLReader xmlReader) {
startIndex = output.length();
}
public void endTag(String tag, Editable output, XMLReader xmlReader) {
stopIndex = output.length();
String content = output.subSequence(startIndex, stopIndex).toString();//获取点击内容
output.setSpan(new CustomClickableSpan(CUSTOM_TAG, content), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Log.e("clickText ", content);
}
}
//绘制图片
class URLDrawable extends BitmapDrawable {
public Bitmap bitmap;
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (bitmap != null) {
canvas.drawBitmap(bitmap, 0, 0, getPaint());
}
}
}
//处理图片
Html.ImageGetter mImageGetter = new Html.ImageGetter() {
private URLDrawable urlDrawable = new URLDrawable();
//加载网络图片
@Override
public Drawable getDrawable(String source) {
Picasso.with(mContext).load(source).into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
urlDrawable.bitmap = bitmap;
urlDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
//不加这个图片加载不上来,不知道什么原因
tv_html.setText(tv_html.getText());
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
return urlDrawable;
}
// 加载本地图片
// @Override
// public Drawable getDrawable(final String source) {
// int id = Integer.parseInt(source);
// Drawable drawable = mContext.getResources().getDrawable(id);
// drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
// .getIntrinsicHeight());
// return drawable;
// }
};