http://www.ithao123.cn/content-9490491.html 这个是一个SpanUtils工具类
*/ public class SpanUtils { public SpanUtils() { } ; /** * 对特定的内容变色 * java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 * 它包括两个类:Pattern和Matcher Pattern 一个Pattern是一个正则表达式经编译后的表现模式。 * Matcher 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。 * 首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 */ private static void dealPattern(int color, SpannableString spannanelString, Pattern patten, int start) { Matcher matcher = patten.matcher(spannanelString);//获取命名的Matcher对象 while (matcher.find()) {//目标字符串里查找下一个匹配子串。 String key = matcher.group();//返回当前查找而获得的与组匹配的所有子串内容 //返回第一个字符的速印的文本匹配正则表达式 true 则继续递归 if (matcher.start() < start) {//返回当前查找所获子串的开始字符在原目标字符串中的位置 continue; } //计算该内容的长度 也就是要替换的字符串的长度 int end = matcher.start() + key.length(); //设置前景色span spannanelString.setSpan(new ForegroundColorSpan(color), matcher.start(), end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); if (end < spannanelString.length()) { //如果整个字符还未验证完则继续 dealPattern(color, spannanelString, patten, end); } break; } } //应为有些是可点击的,所以需要一个方法来处理可点击的内容 // ①先定义一个接口,通过接口的方式将点击事件交给调用者 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();//返回当前查找而获得的与组匹配的所有子串内容 //返回第一个字符的速印的文本匹配正则表达式 true 则继续递归 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, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); if (end < spannableString.length()) { dealClick(spannableString, patten, end, spanClickListener, bean); } break; } } //关键词变色处理方法,这个实际中的使用场景比如地图关键字搜索,匹配到关键字的地址中关键字显示特别颜色 public static SpannableString getKeyWordSpan(int color, String str, String patterStr) { SpannableString spannableString = new SpannableString(str); Pattern patten = Pattern.compile(patterStr, Pattern.CASE_INSENSITIVE); dealPattern(color, spannableString, patten, 0); return spannableString; } //7 @@好友处理,参数中需要传入@的好友列表 public static SpannableString getAtuseSpan(int color, String str, boolean clockable, SpanClickListener spanClickListener, List<User> atUser) { SpannableString spannableString = new SpannableString(str); Pattern pattern; for (User u : atUser) { pattern = Pattern.compile("@" + u.getName(), Pattern.CASE_INSENSITIVE);//启用不区分大小写的匹配。 if (clockable) { dealClick(spannableString, pattern, 0, spanClickListener, u); } dealPattern(color, spannableString, pattern, 0); } return spannableString; }}
/使用
private void testColoredKeywd(){ String str = " 编辑推荐,更多热门分类资源推荐,开发技术共有3018824个资源,课程资源共有1202328个资源,移动开"; SpannableString ardText = SpanUtils.getKeyWordSpan(getResources().getColor(R.color.rad),str,"开发"); tvView.setText(ardText); } private void textAtUser(){ List<User> users = new ArrayList<>(); users.add(new User(1,"又快国庆了")); users.add(new User(2,"你好")); StringBuilder sb = new StringBuilder("呵呵家里好"); for (User u :users){ sb.append("@").append(u.getName()); } sb.append("\n"); try { SpannableString atSpan = SpanUtils.getAtuseSpan(Color.RED,sb.toString(),true, new SpanUtils.SpanClickListener<User>() { @Override public void onSpanClick(User user) { Toast.makeText(MainActivity.this,"@又快国庆了"+user.toString(),Toast.LENGTH_LONG); } },users); tvView.setText(atSpan); tvView.setMovementMethod(LinkMovementMethod.getInstance()); }catch (Exception e){ e.printStackTrace(); } }