Quickly build Android custom emoticon Library

Keywords: github Android


Please respect the original, reproduce it from: http://blog.csdn.net/mabeijianxi/article/details/74779611


brief introduction

The inspiration for this article is classical https://github.com/rockerhieu/emojicon , part of the code is directly face-free copy ing, on which it is more beautiful and useful, and has more customization space.

Final Effect Chart


Source Download and Use Methods

https://github.com/mabeijianxi/android-expression

Realize Ideas

  1. First ask the UI to give me a good picture of the expression, and then save it under the local drawable.

  2. Then whether you write a script or an input, cache all the picture names into an array, an array represents one page of emoticons, how many pages it takes, and how many emoticons a page has depends on the UI's preferences. Of course, you'll find that I've given an empty string space because I want to write a delete button there ~~.

  3. Save its name with its id in a Map, which will make it more efficient for later use.


  4. Put each page of data into a GridView, where each Item is a TextView, and then put these
    GridView joins the ViewPager, and if we don't handle it at this time, the effect should be as follows:

  5. We duplicate a TextView and use Spannable to dynamically replace the corresponding text with pictures, and that's it. (Careful students will find that the number of dots in the 4 and 5 pictures is different. Figure 4 is the latest project. I removed the old emoticons. Figure 5 is the previous one):

Core Code Details

The encapsulated part is not a nagging one. It can be read directly from open source at a glance. Now look directly at some core methods.
  • Text replacement:
    Check if there are any emoticons in a piece of text that match our definition, and if they match, replace them with the corresponding pictures.

    public static Spannable transformExoression(Context context, Spannable text, int emojiSize, int emojiAlignment, int textSize) {
          int textLength = text.length();
    
          HashMap<Integer, Integer> SpanIndex = new HashMap<>();
    
          ExpressionSpan[] oldSpans = text.getSpans(0, textLength, ExpressionSpan.class);
          for (int i = 0; i < oldSpans.length; i++) {
              SpanIndex.put(text.getSpanStart(oldSpans[i]), text.getSpanEnd(oldSpans[i]));
          }
    
          String PATTERN = "\\[jx](.*?)\\[/jx]";
          Pattern p = Pattern.compile(PATTERN);
          Matcher m = p.matcher(text);
          while (m.find()) {
    
              Integer maybeEnd = SpanIndex.get(m.start());
              if ( maybeEnd!=null&&maybeEnd.intValue()== m.end()) {
                  continue;
              }
    
              String beferGroup = m.group();
              Integer index = ExpressionCache.getAllExpressionTable().get(beferGroup);
              int id = -1;
              if (index!=null&&index>=0) {
                  id = index;
              } else {
                  String afterGroup = beferGroup.replace("[jx]", "").replace("[/jx]", "");
    
                  id = context.getResources().getIdentifier(afterGroup, "drawable", context.getPackageName());
              }
              if (id <= 0) {
                  continue;
              }
              text.setSpan(new ExpressionSpan(context, id, emojiSize, emojiAlignment, textSize), m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
          }
          return text;
    
      }

    First, I get all the ExpressionSpans in this text through text.getSpans, which is the expression information. An ExpressionSpan is an expression. We put the starting position of each expression into a HashMap, which is very efficient!You can see that we use regular pictures to identify the text behind us, that is, at the beginning of [jx], [/jx] at the end. Why did I do that earlier to increase efficiency?You can see that if you find a matching word, first I get its start tag, and then put it in the HashMap just now to find its corresponding value. If the value is exactly equal to the end tag of the word we just searched for, then the expression has not changed at all. We don't need to replace it again. This is very useful when typing.I also came up with a solution after you typed in an especially large number of emoticons to create Carton. This way when you type in an emoticon, only the current one will be processed. The other words match but will be completely continue d by us.All we need to do is go down and we just need to cache this string Look inside Map of ID to get the corresponding picture id, that is, execute ExpressionCache.getAllExpressionTable().get(beferGroup).Then you can build an Image Span-like pan.

  • Recent Use List Maintenance

    /**
       * Add Recent Emotions
       *
       * @param str
       */
      public static void addRecentExpression(String str) {
          int endIndex = getEndIndex();
          for (int i = 0; i < ExpressionCache.getRecentExpression().length; i++) {
    //            Prevent duplication
              if (ExpressionCache.getRecentExpression()[i] == str || i == ExpressionCache.getRecentExpression().length - 1) {
                  //                    Up to one page
                  sort(i, str);
                  return;
              }
          }
    
          sort(endIndex, str);
    
      }
    
      /**
       * Move one bit back, keeping only the last 21
       *
       * @param endIndex
       * @param newStr
       */
      private static void sort(int endIndex, String newStr) {
          for (int i = endIndex; i > 0; i--) {
              ExpressionCache.getRecentExpression()[i] = ExpressionCache.getRecentExpression()[i - 1];
          }
          ExpressionCache.getRecentExpression()[0] = newStr;
      }
    
      /**
       * Get the last significant bit
       *
       * @return
       */
      private static int getEndIndex() {
          int lastStr = 0;
          for (int i = 0; i < ExpressionCache.getRecentExpression().length; i++) {
              if (ExpressionCache.getRecentExpression()[i] == null || i == ExpressionCache.getRecentExpression().length - 1) {
                  lastStr = i;
                  break;
              }
          }
          return lastStr;
      }

    First, the container that stores the most recently used emoticons is an array, so I can't determine its normal effective length. My first step is to get a valid length, then simply shift the sort.As long as we click once we check that we don't need to reorder from scratch.

    summary

    I have almost finished writing. Just in this moment, the University goddess chatted with me.Let me teach her to chase another man.Yes, you can.Last paste source address https://github.com/mabeijianxi/android-expression

Posted by marc2000 on Sat, 15 Jun 2019 09:37:50 -0700