Android仿新浪微博、QQ空间等帖子显示(2)
一、介绍
这是新浪微博的一个帖子,刚好包括了话题、表情、@好友三种显示。显示方法上篇已经阐述了,就是使用spannablestring。这篇主要介绍显示这种帖子的解析工具类。
二、实现
1.字符串表示和对应正则表达式
话题用##号括起来
表情用[]表示
@好友昵称
借助正则匹配来解析帖子信息。
话题 -> #[^#]+#
表情 -> [[^]]+]
@好友 -> @好友昵称
2.写一个通用方法,对spanablestring进行正则判断,如果符合要求,则将内容变色
private static void dealpattern(int color, spannablestring spannablestring, pattern patten, int start) throws exception { matcher matcher = patten.matcher(spannablestring); while (matcher.find()) { string key = matcher.group(); // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归 if (matcher.start() < start) { continue; } // 计算该内容的长度,也就是要替换的字符串的长度 int end = matcher.start() + key.length(); //设置前景色span spannablestring.setspan(new foregroundcolorspan(color), matcher.start(), end, spannable.span_exclusive_exclusive); if (end < spannablestring.length()) { // 如果整个字符串还未验证完,则继续。。 dealpattern(color, spannablestring, patten, end); } break; } }
3.应为有些是可点击的,所以需要一个方法来处理可点击的内容
①先定义一个接口,通过接口的方式将点击事件交给调用者
public interface spanclicklistener<t>{ void onspanclick(t t); }
②写一个通用方法,对spanablestring进行正则判断,如果符合要求,将内容设置可点击
private static void dealclick(spannablestring spannablestring, pattern patten, int start, final spanclicklistener spanclicklistener, final object bean){ matcher matcher = patten.matcher(spannablestring); while (matcher.find()) { string key = matcher.group(); // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归 if (matcher.start() < start) { continue; } // 计算该内容的长度,也就是要替换的字符串的长度 int end = matcher.start() + key.length(); spannablestring.setspan(new clickablespan() { @override public void onclick(view widget) { spanclicklistener.onspanclick(bean); } @override public void updatedrawstate(textpaint ds) { super.updatedrawstate(ds); //设置画笔属性 ds.setunderlinetext(false);//默认有下划线 } }, matcher.start(), end, spannable.span_exclusive_exclusive); if (end < spannablestring.length()) { // 如果整个字符串还未验证完,则继续。。 dealclick(spannablestring, patten, end, spanclicklistener, bean); } break; } }
4.表情解析方法(后面会写一篇关于表情的处理)
private void dealexpression(context context, spannablestring spannablestring, pattern patten, int start) throws exception { matcher matcher = patten.matcher(spannablestring); while (matcher.find()) { string key = matcher.group(); if (matcher.start() < start) { continue; } string value = emojimap.get(key); if (textutils.isempty(value)) { continue; } // 通过上面匹配得到的字符串来生成图片资源id int resid = context.getresources().getidentifier(value, "drawable", context.getpackagename()); if (resid != 0) { drawable emoji = context.getresources().getdrawable(resid); int w = (int) (emoji.getintrinsicwidth() * 0.40); int h = (int) (emoji.getintrinsicheight() * 0.40); emoji.setbounds(0, 0, w, h); // 通过图片资源id来得到bitmap,用一个imagespan来包装 imagespan imagespan = new imagespan(emoji); // 计算该图片名字的长度,也就是要替换的字符串的长度 int end = matcher.start() + key.length(); // 将该图片替换字符串中规定的位置中 spannablestring.setspan(imagespan, matcher.start(), end, spannable.span_inclusive_exclusive); if (end < spannablestring.length()) { dealexpression(context, spannablestring, patten, end); } break; } } }
5.关键词变色处理方法,这个实际中的使用场景比如地图关键字搜索,匹配到关键字的地址中关键字显示特别颜色
public static spannablestring getkeywordspan(int color, string str, string patterstr) throws exception { spannablestring spannablestring = new spannablestring(str); pattern patten = pattern.compile(patterstr, pattern.case_insensitive); dealpattern(color, spannablestring, patten, 0); return spannablestring; }
6.话题处理,参数中需要传入话题对象。这里只处理了一个帖子中只有一个话题的情况
public static spannablestring gettopicspan(int color, string str, boolean clickable,spanclicklistener spanclicklistener, topic topic) throws exception { spannablestring spannablestring = new spannablestring(str); pattern patten = pattern.compile(patternstring.topic_pattern, pattern.case_insensitive); if(clickable){ dealclick(spannablestring, patten, 0, spanclicklistener, topic); } dealpattern(color, spannablestring, patten, 0); return spannablestring; }
7.@好友处理,参数中需要传入@的好友列表
public static spannablestring getatuserspan(int color, string str, boolean clickable, spanclicklistener spanclicklistener, list<user> atusers) throws exception { spannablestring spannablestring = new spannablestring(str); pattern patten; for (user u : atusers) { patten = pattern.compile("@" + u.getname(), pattern.case_insensitive); if(clickable){ dealclick(spannablestring, patten, 0, spanclicklistener, u); } dealpattern(color, spannablestring, patten, 0); } return spannablestring; }
8.表情处理,就这么简洁
public static spannablestring getexpressionspan(context context, string str) throws exception { return expressionconvertutil.getinstace().getexpressionstring(context, str); }
三、使用
1.关键字变色
private void testcoloredkeywd() { string string = "android一词的本义指“机器人”,同时也是google于2007年11月5日,android logo相关图片,android logo相关图片(36张)\n"; spannablestring cardtext = null; try { cardtext = spanutils.getkeywordspan(getresources().getcolor(r.color.md_green_600), string, "android"); } catch (exception e) { e.printstacktrace(); } tvcoloredkeywd.settext(cardtext); }
2.话题测试,需要注意的是,让部分内容可点击需要设置tvtopic.setmovementmethod(linkmovementmethod.getinstance());,否则点击无效果
private void testtopic() { string topic = "#舌尖上的大连#四种金牌烤芝士吃法爱吃芝士的盆友不要错过了~l秒拍视频\n"; spannablestring topictext = null; try { topictext = spanutils.gettopicspan(color.blue, topic, true, new spanutils.spanclicklistener<topic>() { @override public void onspanclick(topic t) { toast.maketext(mainactivity.this, "点击话题:" + t.tostring() , toast.length_short).show(); } }, new topic(1, "舌尖上的大连")); } catch (exception e) { e.printstacktrace(); } tvtopic.settext(topictext); //如果想实现点击,必须要设置这个 tvtopic.setmovementmethod(linkmovementmethod.getinstance()); }
3.@好友测试
private void textatusers(){ list<user> users = new arraylist<>(); users.add(new user(1, "好友1")); users.add(new user(2, "好友2")); stringbuilder sb = new stringbuilder("快来看看啊"); for (user u : users) { sb.append("@").append(u.getname()); } sb.append("\n"); try { spannablestring atspan = spanutils.getatuserspan(color.blue, sb.tostring(), true, new spanutils.spanclicklistener<user>() { @override public void onspanclick(user user) { toast.maketext(mainactivity.this, "@好友:" + user.tostring(), toast.length_short).show(); } }, users); tvtestat.settext(atspan); tvtestat.setmovementmethod(linkmovementmethod.getinstance()); } catch (exception e) { e.printstacktrace(); } }
4.表情测试
private void textexpression(){ string exstr = "今天天气很好啊[呲牙],是不是应该做点什么[色]"; spannablestring span = null; try { span = spanutils.getexpressionspan(this, exstr); } catch (exception e) { e.printstacktrace(); } tvexpression.settext(span); }
效果图
下载:https://github.com/linechen/spannablestringdemo
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Java连接六类数据库技巧全攻略
下一篇: PHP获取页面执行时间的方法(推荐)