国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android仿新浪微博、QQ空間等帖子顯示(2)

2019-12-12 05:07:32
字體:
供稿:網(wǎng)友

一、介紹

這是新浪微博的一個帖子,剛好包括了話題、表情、@好友三種顯示。顯示方法上篇已經(jīng)闡述了,就是使用SpannableString。這篇主要介紹顯示這種帖子的解析工具類。

二、實現(xiàn)

1.字符串表示和對應(yīng)正則表達式

話題用##號括起來
表情用[]表示
@好友昵稱
借助正則匹配來解析帖子信息。

話題 -> #[^#]+#
表情 -> [[^]]+]
@好友 -> @好友昵稱

2.寫一個通用方法,對spanableString進行正則判斷,如果符合要求,則將內(nèi)容變色

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 則繼續(xù)遞歸   if (matcher.start() < start) {    continue;   }   // 計算該內(nèi)容的長度,也就是要替換的字符串的長度   int end = matcher.start() + key.length();   //設(shè)置前景色span   spannableString.setSpan(new ForegroundColorSpan(color), matcher.start(), end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);   if (end < spannableString.length()) {    // 如果整個字符串還未驗證完,則繼續(xù)。。    dealPattern(color, spannableString, patten, end);   }   break;  } }

3.應(yīng)為有些是可點擊的,所以需要一個方法來處理可點擊的內(nèi)容

①先定義一個接口,通過接口的方式將點擊事件交給調(diào)用者

 public interface SpanClickListener<T>{  void onSpanClick(T t); }

②寫一個通用方法,對spanableString進行正則判斷,如果符合要求,將內(nèi)容設(shè)置可點擊

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 則繼續(xù)遞歸   if (matcher.start() < start) {    continue;   }   // 計算該內(nèi)容的長度,也就是要替換的字符串的長度   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);     //設(shè)置畫筆屬性     ds.setUnderlineText(false);//默認有下劃線    }   }, matcher.start(), end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);   if (end < spannableString.length()) {    // 如果整個字符串還未驗證完,則繼續(xù)。。    dealClick(spannableString, patten, end, spanClickListener, bean);   }   break;  } }

4.表情解析方法(后面會寫一篇關(guān)于表情的處理)

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();    // 將該圖片替換字符串中規(guī)定的位置中    spannableString.setSpan(imageSpan, matcher.start(), end,      Spannable.SPAN_INCLUSIVE_EXCLUSIVE);    if (end < spannableString.length()) {     dealExpression(context, spannableString, patten, end);    }    break;   }  } }

5.關(guān)鍵詞變色處理方法,這個實際中的使用場景比如地圖關(guān)鍵字搜索,匹配到關(guān)鍵字的地址中關(guān)鍵字顯示特別顏色

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.話題處理,參數(shù)中需要傳入話題對象。這里只處理了一個帖子中只有一個話題的情況

 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.@好友處理,參數(shù)中需要傳入@的好友列表

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.關(guān)鍵字變色

private void testColoredKeywd() {  String string = "Android一詞的本義指“機器人”,同時也是Google于2007年11月5日,Android logo相關(guān)圖片,Android logo相關(guān)圖片(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.話題測試,需要注意的是,讓部分內(nèi)容可點擊需要設(shè)置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);  //如果想實現(xiàn)點擊,必須要設(shè)置這個  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 = "今天天氣很好啊[呲牙],是不是應(yīng)該做點什么[色]";  SpannableString span = null;  try {   span = SpanUtils.getExpressionSpan(this, exStr);  } catch (Exception e) {   e.printStackTrace();  }  tvExpression.setText(span); }

效果圖

下載:https://github.com/LineChen/SpannableStringDemo

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 海原县| 南昌市| 晋州市| 文山县| 集贤县| 太原市| 宝鸡市| 江山市| 广安市| 噶尔县| 赣榆县| 菏泽市| 凌云县| 曲阳县| 富川| 方正县| 湛江市| 隆安县| 巴塘县| 贵定县| 浦北县| 凌海市| 故城县| 柘城县| 湖北省| 中西区| 雅江县| 墨江| 星子县| 湖南省| 渝北区| 隆尧县| 宁都县| 乌兰县| 西城区| 敖汉旗| 宁强县| 诸暨市| 贡山| 宝山区| 雅安市|