Androidは新浪微博、QQ空間などの書き込みをまねて表示します(2)


紹介します

これは新浪微博の1つの招待状で、ちょうど話題、表情、@親友の3種類の表示を含みました。表示方法は前編で述べましたが、Spannable Stringを使います。この記事は主にこのような書き込みを示す解析ツールを紹介します。
実現する
1.文字列表現と対応正規表現
話題は菗という字でくくります。
表情を[]で表します
@親友のニックネーム
正規のマッチングを使ってスレッド情報を解析します。
話題->(^𞃳)+噫
表情->[^]+]
@親友->@親友のニックネーム
2.共通の方法を書いて、spanbleStringを正則で判断し、要求に符合すると内容が変色する

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);
 }
②共通の方法を書いて、spanbleStringを正則的に判断し、要求に該当する場合は、内容設定をクリックしてもいいです。

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 )
"; 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.set MoventMethod(LinkMovement Method.getInstance();さもなくばクリックして効果がありません。

private void testTopic() {
  String topic = "#      #                     ~L    
"; 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("
"); 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
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。