Android输入框添加emoje表情图标的实现代码

前言

再次写聊天的时候才发现,代码积累是一件非常重要的事情,就如这篇博客的意图其实就是代码积累的目的,其实没什么难度,但是一件很琐碎的事情真的也需要时间去完成和调试,所以,获取你在写一个功能的时候会觉得并没有多难,但是如果可以最好把代码整理/积累下来。

demo描述

demo的功能其实就是仿照微信的 聊天 emoje 选择,采用了 viewpager+gridView 的方案,不过有空我会补上 recyclerView 的方案,目前还是先把功能实现了再说。另外在 TextView 和 EditText 中添加 emoje ,可以看看这篇博客:Android中使用TextView及EditText来实现表情图标的显示及插入功能 ,这篇博客中介绍了两种方法:

方法一:使用Html.fromHtml解析, 方法二:使用Bitmap直接画出来,我采用了第二种方法,使用bitmap画出来。

Read the fucking code

思路:既然是 viewpager + gridview 那么,先从大方向入手,完成 viewpager,再去完成 gridview。PS:代码里面使用了 RxJava、lambda、ButterKnife、EventBus、Glide。

这里将整个底部布局写成了一个组合的ViewGroup – ChatBottomBar,先从布局开始。

ChatBottomBar 的 XML – chat_bottom.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:animateLayoutChanges="true"
  android:orientation="vertical">

  <include layout="@layout/chat_bottom_input"></include>
  <include layout="@layout/chat_bottom_function1"></include>

</LinearLayout>

以下分别是 输入框的 xml 和 Emoji 的 xml:

chat_bottom_input:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">

  <RelativeLayout
    android:id="@+id/rl_input"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#f0f0f0">

    <ImageView
      android:id="@+id/showMore"
      android:layout_width="42dp"
      android:layout_height="60dp"
      android:paddingBottom="5dp"
      android:paddingLeft="9dp"
      android:paddingTop="9dp"
      android:src="@mipmap/ic_launcher" />

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="35dp"
      android:layout_centerVertical="true"
      android:layout_marginRight="15dp"
      android:layout_toRightOf="@+id/showMore"
      android:background="@drawable/shape_white_corner"
      android:gravity="center_vertical"
      android:orientation="horizontal">

      <ImageView
        android:layout_width="45dp"
        android:layout_height="40dp"
        android:paddingBottom="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="5dp"
        android:paddingTop="10dp"
        android:src="@mipmap/ic_launcher" />

      <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginRight="10dp"
        android:background="@null"
        android:gravity="center_vertical"
        android:hint="说点什么"
        android:maxLines="3"
        android:textColor="#999999"
        android:textColorHint="#dddddd"
        android:textSize="13sp" />

    </LinearLayout>

  </RelativeLayout>

</merge>

chat_bottom_function1:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#ffffff"
  android:orientation="vertical">

  <android.support.v4.view.ViewPager
    android:id="@+id/emojes"
    android:layout_width="match_parent"
    android:layout_height="110dp"></android.support.v4.view.ViewPager>

</LinearLayout>

首先是 viewpager 填充 gridView,从 PageAdapter 看起,看看需要哪些数据:

package cjh.emojicondemo;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.GridView;

import java.util.ArrayList;

/**
 * Created by cjh on 16-11-8.
 */

public class EmojiPageAdapter extends PagerAdapter {

  private ArrayList<GridView> mLists;

  public EmojiPageAdapter(Context context, ArrayList<GridView> array) {
    this.mLists = array;
  }

  @Override
  public int getCount() {
    return mLists.size();
  }

  @Override
  public boolean isViewFromObject(View arg0, Object arg1) {

    return arg0 == arg1;
  }

  @Override
  public Object instantiateItem(View arg0, int arg1) {
    ((ViewPager) arg0).addView(mLists.get(arg1));
    return mLists.get(arg1);
  }

  @Override
  public void destroyItem(View arg0, int arg1, Object arg2) {
    ((ViewPager) arg0).removeView((View) arg2);
  }
}

其实基本就是PagerAdapter的模板代码,需要的仅仅只是 gridView,看下在ChatbottomBar中的代码:

@BindView(R.id.emojes)
android.support.v4.view.ViewPager emojes;
....
//每一页有24个表情,然后使用Math的ceil函数,计算出我们需要的最小页数
 private void initEmoje() {
    int pageCount = (int) Math.ceil(EmojiUtils.emojis.length / 24.0f);
    ArrayList<GridView> pageData = new ArrayList<>();
    for (int i = 0; i < pageCount; i++) {
      GridView gv = getGridView(i);
      pageData.add(gv);
    }
    emojes.setAdapter(new EmojiPageAdapter(context, pageData));
  }

大结构基本就是这样了,接着就是小细节了,比如gridView的创建和展示:

 @NonNull
  private GridView getGridView(int i) {
    GridView gv = new GridView(context);
    gv.setVerticalScrollBarEnabled(false);
    gv.setAdapter(new EmojiGridAdapter(context, i));
    gv.setGravity(Gravity.CENTER);
    gv.setClickable(true);
    gv.setFocusable(true);
    gv.setNumColumns(8);
    return gv;
  }

adapter:

package cjh.emojicondemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import org.greenrobot.eventbus.EventBus;

/**
 * Created by cjh on 16-11-8.
 */

public class EmojiGridAdapter extends BaseAdapter {

  private Context context;
  private int page;

  public EmojiGridAdapter(Context context, int page) {
    this.context = context;
    this.page = page;
  }

  @Override
  public int getCount() {
    return 24;
  }

  @Override
  public Object getItem(int i) {
    return null;
  }

  @Override
  public long getItemId(int i) {
    return 0;
  }

  @Override
  public View getView(int i, View view, ViewGroup viewGroup) {

    ViewHolder holder = null;
    if (view == null) {
      view = LayoutInflater.from(context).inflate(R.layout.chat_emoji, null);
      holder = new ViewHolder();
      holder.image = (ImageView) view.findViewById(R.id.image);
      view.setTag(holder);
    }

    holder = (ViewHolder) view.getTag();
    int position = page * 23 + i;
    if (position < EmojiUtils.emojis.length)
      ImageLoader.load(context, EmojiUtils.icons[position], holder.image);
    else
      holder.image.setVisibility(View.GONE);
    holder.image.setOnClickListener(view1 -> EventBus.getDefault().post(new EmojiEvent(EmojiUtils.emojis[page * 23 + i])));

    return view;
  }

  static class ViewHolder {
    public ImageView image;
  }
}

在这里,点击时间的传递我使用的是EventBus。

大结构基本已经OK了,接着就要看比较核心的部分,Emoji 的处理,在接收到Event事件时,调用了chatBottomBar.appandEmoje(emojiEvent.s)

@Subscribe
  public void onEmojiEvent(EmojiEvent emojiEvent) {
    chatBottomBar.appandEmoje(emojiEvent.s);
  }

那么来看看ChatBottomBar的代码:

public void appandEmoje(String s) {
    rx.Observable
        .just(s)
        .subscribeOn(Schedulers.io())
        .map(s1 -> {
          SpannableString emojeText = EmojiUtils.getEmojiText(editText.getText().toString() + s1);
          return emojeText;
        })
        .unsubscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(s2 -> {
          editText.setText("");
          editText.append(s2);
        });
  }

上面代码使用了RXJAVA,可以看到真正的核心是在
EmojiUtils.getEmojiText(editText.getText().toString() + s1);
return emojeText;这行代码里面。

那么就来看看 EmojiUtils 的代码吧:

package cjh.emojicondemo;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
import android.util.SparseArray;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Inflater;

/**
 * Created by cjh on 16-11-7.
 */

public class EmojiUtils {

  private static HashMap<Pattern, Integer> emoMap = new HashMap<>();

  public static final String DELETE_KEY = "em_delete_delete_expression";

  public static String[] emojis = new String[]{
      "[微笑]",
      "[撇嘴]",
      "[色]",
      "[发呆]",
      "[得意]",
      "[流泪]",
      "[害羞]",
      "[闭嘴]",
      "[睡]",
      "[大哭]",
      "[尴尬]",
      "[发怒]",
      "[调皮]",
      "[呲牙]",
      "[惊讶]",
      "[难过]",
      "[酷]",
      "[冷汗]",
      "[抓狂]",
      "[吐]",
      "[偷笑]",
      "[愉快]",
      "[白眼]",
      "[傲慢]",
      "[饥饿]",
      "[困]",
      "[惊恐]",
      "[流汗]",
      "[憨笑]",
      "[悠闲]",
      "[奋斗]",
      "[咒骂]",
      "[疑问]",
      "[嘘]",
      "[晕]",
      "[疯了]",
      "[衰]",
      "[骷髅]",
      "[敲打]",
      "[再见]",
      "[擦汗]",
      "[抠鼻]",
      "[鼓掌]",
      "[糗大了]",
      "[坏笑]",
      "[左哼哼]",
      "[右哼哼]",
      "[哈欠]",
      "[鄙视]",
      "[委屈]",
      "[快哭了]",
      "[阴险]",
      "[亲亲]",
      "[吓]",
      "[可怜]",
      "[菜刀]",
      "[西瓜]",
      "[啤酒]",
      "[篮球]",
      "[乒乓]",
      "[咖啡]",
      "[饭]",
      "[猪头]",
      "[玫瑰]",
      "[凋谢]",
      "[嘴唇]",
      "[爱心]",
      "[心碎]",
      "[蛋糕]",
      "[闪电]",
      "[炸弹]",
      "[刀]",
      "[足球]",
      "[瓢虫]",
      "[便便]",
      "[月亮]",
      "[太阳]",
      "[礼物]",
      "[拥抱]",
      "[强]",
      "[弱]",
      "[握手]",
      "[胜利]",
      "[抱拳]",
      "[勾引]",
      "[拳头]",
      "[差劲]",
      "[爱你]",
      "[NO]",
      "[OK]"
  };

  public static int[] icons = new int[]{
      R.drawable.ee_1,
      R.drawable.ee_2,
      R.drawable.ee_3,
      R.drawable.ee_4,
      R.drawable.ee_5,
      R.drawable.ee_6,
      R.drawable.ee_7,
      R.drawable.ee_8,
      R.drawable.ee_9,
      R.drawable.ee_10,
      R.drawable.ee_11,
      R.drawable.ee_12,
      R.drawable.ee_13,
      R.drawable.ee_14,
      R.drawable.ee_15,
      R.drawable.ee_16,
      R.drawable.ee_17,
      R.drawable.ee_18,
      R.drawable.ee_19,
      R.drawable.ee_20,
      R.drawable.ee_21,
      R.drawable.ee_22,
      R.drawable.ee_23,
      R.drawable.ee_24,
      R.drawable.ee_25,
      R.drawable.ee_26,
      R.drawable.ee_27,
      R.drawable.ee_28,
      R.drawable.ee_29,
      R.drawable.ee_30,
      R.drawable.ee_31,
      R.drawable.ee_32,
      R.drawable.ee_33,
      R.drawable.ee_34,
      R.drawable.ee_35,
      R.drawable.ee_36,
      R.drawable.ee_37,
      R.drawable.ee_38,
      R.drawable.ee_39,
      R.drawable.ee_40,
      R.drawable.ee_41,
      R.drawable.ee_42,
      R.drawable.ee_43,
      R.drawable.ee_44,
      R.drawable.ee_45,
      R.drawable.ee_46,
      R.drawable.ee_47,
      R.drawable.ee_48,
      R.drawable.ee_49,
      R.drawable.ee_50,
      R.drawable.ee_51,
      R.drawable.ee_52,
      R.drawable.ee_53,
      R.drawable.ee_54,
      R.drawable.ee_55,
      R.drawable.ee_56,
      R.drawable.ee_57,
      R.drawable.ee_58,
      R.drawable.ee_59,
      R.drawable.ee_60,
      R.drawable.ee_61,
      R.drawable.ee_62,
      R.drawable.ee_63,
      R.drawable.ee_64,
      R.drawable.ee_65,
      R.drawable.ee_66,
      R.drawable.ee_67,
      R.drawable.ee_68,
      R.drawable.ee_69,
      R.drawable.ee_70,
      R.drawable.ee_71,
      R.drawable.ee_72,
      R.drawable.ee_73,
      R.drawable.ee_74,
      R.drawable.ee_75,
      R.drawable.ee_76,
      R.drawable.ee_77,
      R.drawable.ee_78,
      R.drawable.ee_79,
      R.drawable.ee_80,
      R.drawable.ee_81,
      R.drawable.ee_82,
      R.drawable.ee_83,
      R.drawable.ee_84,
      R.drawable.ee_85,
      R.drawable.ee_86,
      R.drawable.ee_87,
      R.drawable.ee_88,
      R.drawable.ee_89,
      R.drawable.ee_90,
  };

  static {
    for (int i = 0; i < emojis.length; i++) {
      emoMap.put(Pattern.compile(Pattern.quote(emojis[i])), icons[i]);
    }
  }

  public static SpannableString getEmojiText(String s) {
    SpannableString spannable = new SpannableString(s);
    for (Map.Entry<Pattern, Integer> entry : emoMap.entrySet()) {
      Matcher matcher = entry.getKey().matcher(spannable);
      while (matcher.find()) {
        for (ImageSpan span : spannable.getSpans(matcher.start(),
            matcher.end(), ImageSpan.class))
          if (spannable.getSpanStart(span) >= matcher.start()
              && spannable.getSpanEnd(span) <= matcher.end())
            spannable.removeSpan(span);
          else
            break;
        Drawable drawable = MainActivity.context.getResources().getDrawable(entry.getValue());
        drawable.setBounds(0, 0, 60, 60);
        ImageSpan imageSpan = new ImageSpan(drawable);
        spannable.setSpan(imageSpan,
            matcher.start(), matcher.end(),
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
      }
    }
    return spannable;
  }
}

这里为了方便知道插入表情的位置,我将emoji对应的中文转化成了Pattern对象,在getEmojiText里面做了遍历查询比对,这也就是为什么我会使用RX来异步操作。

基本就到这里了,回过来看写的内容,自己都懒得吐槽,不过,好在只要有具体的demo,能读代码,有没有讲解其实都还好,也不用怕自己之后看不懂了。

源码下载:https://github.com/cjhandroid/EmojiInputDemo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android开发之APP安装后在桌面上不显示应用图标的解决方法

    本文实例讲述了Android开发之APP安装后在桌面上不显示应用图标的解决方法.分享给大家供大家参考,具体如下: 一.问题: 前几天在写项目的时候运行的时候突然Android桌面上没有了应用图标,但是应用里面下载的应用有.调试版本和发布正式的版本都没有,之前以为是因为用了不同的keystore发布了两个不同的正式版本造成的问题.后来在看别人的文章才知道是什么问题. 二.分析: 原因就是activity中的intent-filter用了不同的data和action属性.intent-filter必

  • Android App更改应用的图标的实现方法

    Android App更改应用的图标的实现方法 一般情况下,我们App图标在Androidmanifest.xml中设置,通过Application android:icon属性指定,写法如下: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package=&q

  • Android实现下拉刷新的视图和图标的旋转

    一.下拉才出现的视图 pull_to_refresh_header.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pull_to_refresh_header" android:orienta

  • Android获取高清app图标代码分享

    Android获取高清app图标只有一个方法,具体内容如下 public synchronized static Drawable getIconFromPackageName(String packageName, Context context) { PackageManager pm = context.getPackageManager(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)

  • Android中正确使用字体图标(iconfont)的方法

    字体图标 字体图标是指将图标做成字体文件(.ttf),从而代替传统的png等图标资源. 使用字体图标的优点和缺点分别为: 优点: 1. 可以高度自定义图标的样式(包括大小和颜色),对于个人开发者尤其适用 2. 可以减少项目和安装包的大小(特别你的项目中有很多图片icon时,效果将是M级) 3. 几乎可以忽略屏幕大小和分辨率,做到更好的适配 4. 使用简单 -- 缺点:        1. 只能是一些简单的icon,不能代替如背景图.9图等资源 2. 一些需要文字说明的icon,图片资源将会是更好

  • Android实现底部图标与Fragment的联动实例

    本文介绍了ndroid实现底部图标与Fragment的联动,分享给大家,希望此文章对各位有所帮助. 效果如下: 1.首先在res下的drawable下新建四个图标的xml,分别把图标的选中和未选中的状态设置好,所有的图片可以放在res下新建的一个drawable-xhdpi目录下,这里仅展示一个图标的xml <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="ht

  • Android 桌面图标右上角显示未读消息数字

    背景: 在Android原生系统中,众所周知不支持桌面图标显示未读消息提醒的数字,虽然第三方控件BadgeView可以实现应用内的数字提醒.但对于系统的图标,特别是app的logo图标很难实现数字标志,即使是绘图的方式不断修改,但这种方式天生弊端,实用性很差.但幸运的是,一些强大的手机厂商(小米,三星,索尼)提供了私有的API,但也带来了难度,API的不同就意味着代码量的增加和兼容性问题更加突出. 现在我们来看看他们是如何实现的: 实现原理: 首先我们要明白 并不是应用本身处理对启动图标进行修改

  • Android如何动态改变App桌面图标

    时不时的我们就会发现,一些我们常见的应用,比如某宝,某东,在一些特殊的日子中,比如双十一,元旦,为了迎合这样一个日子的气氛,在桌面的应用图标就会发生改变,其实对于这样的一个桌面图标更换,Android中为我们提供了AndroidManifest.xml里的<activity-alias>标签实现方式(更多文章请关注我的微信公众账号,左边二维码). 我们知道,我们每写一个 Activity就要在AndroidManifest进行配置一下,我们才可以正常的启动它,除此之外,我们还可以对它设置一个别

  • Android输入框添加emoje表情图标的实现代码

    前言 再次写聊天的时候才发现,代码积累是一件非常重要的事情,就如这篇博客的意图其实就是代码积累的目的,其实没什么难度,但是一件很琐碎的事情真的也需要时间去完成和调试,所以,获取你在写一个功能的时候会觉得并没有多难,但是如果可以最好把代码整理/积累下来. demo描述 demo的功能其实就是仿照微信的 聊天 emoje 选择,采用了 viewpager+gridView 的方案,不过有空我会补上 recyclerView 的方案,目前还是先把功能实现了再说.另外在 TextView 和 EditT

  • Android 8.1隐藏状态栏图标的实例代码

    近期客户需求,状态栏只显示时间和电池图标,如图 状态栏图标的布局文件在frameworks\base\packages\SystemUI\res\layout\status_bar.xml,主要包括通知,定位,蓝牙,信号,时间,电池等图标,只要在相应的布局文件中加入属性android:visibility="invisible" 或者"gone"即可 <?xml version="1.0" encoding="utf-8"

  • Django添加favicon.ico图标的示例代码

    所谓favicon,即Favorites Icon的缩写,让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站. 默认情况下,浏览器访问一个网站的时候,同时还会向服务器请求"/favicon.ico"这个URL,目的是获取网站的图标. 若是没有配置的话,Django就会返回一个404错误,并且浏览器接收到这个404错误后不会显示出来,一般不会被察觉. 但是服务器要是开启日志记录的话,这错误就会一直记录下来,累积一大堆无用的记录. 添加favicon.ico图标的方法有两种

  • Android实现动态改变app图标的示例代码

    本文介绍了动态改变app图标,分享给大家,具体如下: 代码实现如下: <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"&

  • bootstrap中添加额外的图标实例代码

    说明 可以针对校验状态为输入框添加额外的图标.只需设置相应的 .has-feedback 类并添加正确的图标即可 示例 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <m

  • android如何添加桌面图标和卸载程序后自动删除图标

    1:创建图标如下 复制代码 代码如下: Intent intent = new Intent(); intent.setClass(this, SplashActivity.class); Intent addShortcut = new Intent(ACTION_ADD_SHORTCUT); Parcelable icon = Intent.ShortcutIconResource.fromContext(this, R.drawable.icon); addShortcut.putExtr

  • android高仿微信表情输入与键盘输入代码(详细实现分析)

    表情与键盘的切换输入大部分IM都会需要到,之前自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个困扰了我些时间,不过所幸在Github(其代码整体结构很不错)并且在论坛上找些解决思路,再加上研究了好几个开源项目的代码,最后终于苦逼地整合出比较不错的实现效果(这里不仅给出了实现方案,还提供一个可拓展的fragment模板以便大家实现自己的表情包)代码我已进行另外的封装与拓展,大家需要其他表情的话只需要根据fragment模板实现自己的表情界面,然后根据工厂类获取即可,实现效果

  • Android高仿微信表情输入与键盘输入详解

    最近公司在项目上要使用到表情与键盘的切换输入,自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个相当困扰我,不过所幸在Github(其中一个不错的开源项目,其代码整体结构很不错)并且在论坛上找些解决方案,再加上我也是研究了好多个开源项目的代码,最后才苦逼地整合出比较不错的实现效果,可以说跟微信基本一样(嘿嘿,只能说目前还没发现大Bug,若发现大家一起日后慢慢完善,这里我也只是给出了实现方案,拓展其他表情我并没有实现哈,不过代码中我实现了一个可拓展的fragment模板以便大

  • Android编程实现QQ表情的发送和接收完整实例(附源码)

    本文实例讲述了Android编程实现QQ表情的发送和接收.分享给大家供大家参考,具体如下: 在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下QQ表情,图片资源完全copy的QQ.apk,解压就可以得到,这里不细说. 下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾.. 先看一下效果图: 首先进入界面:(完全仿照QQ) 点击一下上面的表情图标: 选择一些表情,输入一些文字混合: 点击发送: 可以看到文字和表情图片都一起显示出来了. 下面列出一些关键代码: 表情工具类Exp

  • Android自带emoji表情的使用方法详解

    什么是emoji表情 emoji表情是一种表情符号,在代码中它现在其实是一组遵循Unicode的编码,即每一个表情符号都对应了一个Unicode编码.更进一步说,emoji表情实际上是一组Unicode编码与一组表情描述之间的对应.注意,这里所说的不是表情图片,而是表情描述.那么图片的实现是由谁来负责的呢?图片是由各个系统或者软件针对统一的表情描述来各自实现的,他们都遵循统一的Unicode编码规范.也就是说Unicode编码其所对应的表情描述是统一的,是所有人都要共同遵守的一套标准或者规范,而

随机推荐