百行代码集成Emoji并转成iOS、后台可识别字符
最近被提了一个BUG,在iOS提交了包含Emoji表情的文字,在Android中却识别不了,还可能导致后台接口出错(¬_¬)…于是,开始了我Emoji爬坑之路。
效果图:
集成Emoji表情
说到怎么集成Emoji表情,Github中一搜有一大堆,我这里用的是比较热门的emojicon,这个库提供的表情都比较全,但也会导致Apk包增加几兆(数千个表情-_-!),作者提供了EmojiconTextView、EmojiconEditText、EmojiconsFragment,其中EmojiconsFragment是写好的Emoji表情选择框(有些丑..得根据需求去修改),至于如何使用,可以去Github看文档。
将Emoji表情传给后台并解析后台返回的Emoji字符
在Android中调试看到的EditText.getText().toString的Emoji表情是后台无法识别的,我们需要将它转换成一些可见的字符串,并且这个字符串格式与iOS开发人员协定好,使得三个端都可识别。刚开始,我是将它通过EmojiUtils工具类转成Unicode十六进制字符串,拿到后台返回json数据时逐个字节判断是否包含Emoji表情,再将Emoji表情的Unicode字符串转成表情。
public class EmojiUtils {
/**
* 将Unicode字符转成中文
* @param src
* @return
*/
public static String unicode2Emoji(String src) {
if (TextUtils.isEmpty(src)) {
return "";
}
StringBuffer retBuf = new StringBuffer();
int maxLoop = src.length();
for (int i = 0; i < maxLoop; i++) {
if (src.charAt(i) == '\\') {
if ((i < maxLoop - 5) && ((src.charAt(i + 1) == 'u') || (src.charAt(i + 1) == 'U'))) {
try {
retBuf.append((char) Integer.parseInt(src.substring(i + 2, i + 6), 16));
i += 5;
} catch (NumberFormatException localNumberFormatException) {
retBuf.append(src.charAt(i));
}
} else {
retBuf.append(src.charAt(i));
}
} else {
retBuf.append(src.charAt(i));
}
}
return retBuf.toString();
}
/**
* 将字符串中的Emoji表情转换成Unicode编码
* @param src
* @return
*/
public static String emoji2Unicode(String src) {
StringBuffer unicode = new StringBuffer();
for (int i = 0; i < src.length(); i++) {
char c = src.charAt(i);
int codepoint = src.codePointAt(i);
if(isEmojiCharacter(codepoint)) {
unicode.append("\\u").append(Integer.toHexString(c));
} else {
unicode.append(c);
}
}
return unicode.toString();
}
/**
* 判断是否包含Emoji符号
* @param codePoint
* @return
*/
public static boolean isEmojiCharacter(int codePoint) {
return (codePoint >= 0x2600 && codePoint <= 0x27BF) // 杂项符号与符号字体
|| codePoint == 0x303D
|| codePoint == 0x2049
|| codePoint == 0x203C
|| (codePoint >= 0x2000 && codePoint <= 0x200F)//
|| (codePoint >= 0x2028 && codePoint <= 0x202F)//
|| codePoint == 0x205F //
|| (codePoint >= 0x2065 && codePoint <= 0x206F)//
/* 标点符号占用区域 */
|| (codePoint >= 0x2100 && codePoint <= 0x214F)// 字母符号
|| (codePoint >= 0x2300 && codePoint <= 0x23FF)// 各种技术符号
|| (codePoint >= 0x2B00 && codePoint <= 0x2BFF)// 箭头A
|| (codePoint >= 0x2900 && codePoint <= 0x297F)// 箭头B
|| (codePoint >= 0x3200 && codePoint <= 0x32FF)// 中文符号
|| (codePoint >= 0xD800 && codePoint <= 0xDFFF)// 高低位替代符保留区域
|| (codePoint >= 0xE000 && codePoint <= 0xF8FF)// 私有保留区域
|| (codePoint >= 0xFE00 && codePoint <= 0xFE0F)// 变异选择器
|| codePoint >= 0x10000; // Plane在第二平面以上的,char都不可以存,全部都转
}
}
后来找到一个第三方库(https://github.com/vdurmont/emoji-java/),它可以将Emoji表情转换成各种格式字符串,包括我们想要的Unicode编码,最新Emoji表情Unicode对照表:http://apps.timwhitlock.info/emoji/tables/unicode
举个栗子
在app的build.gradle中加入:
//Emoji表情:https://github.com/rockerhieu/emojicon
compile 'io.github.rockerhieu:emojicon:+'
//Emoji表情转换成各类可见字符串:https://github.com/vdurmont/emoji-java/
compile 'com.vdurmont:emoji-java:+'
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/ll_main_bottom"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/padding"
android:text="Emoji表情展示:"
android:textColor="@color/colorAccent"/>
<io.github.rockerhieu.emojicon.EmojiconTextView
android:id="@+id/tv_main_emoji"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/padding"
android:text="Emoji表情转Unicode编码:"
android:textColor="@color/colorAccent"/>
<TextView
android:id="@+id/tv_main_unicode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/padding"
android:text="Emoji表情转Unicode(10进制)编码:"
android:textColor="@color/colorAccent"/>
<TextView
android:id="@+id/tv_main_unicode_dec"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Emoji表情转Unicode(16进制)编码:"
android:textColor="@color/colorAccent"/>
<TextView
android:id="@+id/tv_main_unicode_hex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/padding"
android:text="Emoji表情转iOS可识别的Aliase:"
android:textColor="@color/colorAccent"/>
<TextView
android:id="@+id/tv_main_aliase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/padding"
android:text="过滤Emoji表情:"
android:textColor="@color/colorAccent"/>
<TextView
android:id="@+id/tv_main_emoji_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding"/>
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="@+id/ll_main_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<io.github.rockerhieu.emojicon.EmojiconEditText
android:id="@+id/et_main_bottom"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"/>
<ImageView
android:id="@+id/iv_main_emoji"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:src="@mipmap/icon_happy_face"/>
<Button
android:id="@+id/btn_main_unicode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="编码转换"/>
</LinearLayout>
<FrameLayout
android:id="@+id/fl_main_bottom_emoji"
android:layout_width="match_parent"
android:layout_height="250dp"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
MainActivity
public class MainActivity extends AppCompatActivity implements EmojiconGridFragment.OnEmojiconClickedListener, EmojiconsFragment.OnEmojiconBackspaceClickedListener {
@BindView(R.id.tv_main_emoji)
EmojiconTextView tvEmoji;
@BindView(R.id.tv_main_unicode)
TextView tvUnicode;
@BindView(R.id.tv_main_unicode_dec)
TextView tvUnicodeDec;
@BindView(R.id.tv_main_unicode_hex)
TextView tvUnicodeHex;
@BindView(R.id.tv_main_aliase)
TextView tvAliase;
@BindView(R.id.tv_main_emoji_filter)
TextView tvEmojiFilter;
@BindView(R.id.fl_main_bottom_emoji)
FrameLayout flBottomEmoji;
@BindView(R.id.et_main_bottom)
EmojiconEditText etBottom;
private Context mContext;
private FragmentManager mFragmentManager;
private EmojiconsFragment mEmojiconsFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mContext = this;
mFragmentManager = getSupportFragmentManager();
if(mEmojiconsFragment == null) {
mEmojiconsFragment = EmojiconsFragment.newInstance(false);
}
}
/**
* 显示表情选择框
*/
private void showEmojiSelector() {
flBottomEmoji.setVisibility(View.VISIBLE);
if(mEmojiconsFragment.isAdded()) {
mFragmentManager.beginTransaction().show(mEmojiconsFragment).commit();
} else {
mFragmentManager.beginTransaction().add(R.id.fl_main_bottom_emoji, mEmojiconsFragment).commit();
}
}
/**
* 隐藏表情选择框
*/
private void hideEmojiSelector() {
flBottomEmoji.setVisibility(View.GONE);
if(mEmojiconsFragment.isAdded()) {
mFragmentManager.beginTransaction().hide(mEmojiconsFragment).commit();
}
}
@OnClick(R.id.et_main_bottom)
public void onEditTextClick(View v) {
//软键盘弹出时,隐藏表情选择框
if(KeyBoardUtils.isKeyboardShown(mContext, etBottom)) {
hideEmojiSelector();
}
}
@OnClick(R.id.iv_main_emoji)
public void emoji() {
//显示或隐藏Emoji表情选择框
KeyBoardUtils.closeKeybord(mContext, etBottom);
if(!flBottomEmoji.isShown()) {
showEmojiSelector();
} else {
hideEmojiSelector();
}
}
@OnClick(R.id.btn_main_unicode)
public void unicode() {
//将Emoji表情转换成各种可见字符串
KeyBoardUtils.closeKeybord(mContext, etBottom);
String content = etBottom.getText().toString().trim();
tvEmoji.setText(content);
tvUnicode.setText(EmojiParser.parseToUnicode(content));
tvUnicodeDec.setText(EmojiParser.parseToHtmlDecimal(content));
tvUnicodeHex.setText(EmojiParser.parseToHtmlHexadecimal(content));
tvAliase.setText(EmojiParser.parseToAliases(content));
tvEmojiFilter.setText(EmojiParser.removeAllEmojis(content));
}
@Override
public void onEmojiconBackspaceClicked(View v) {
//删除EditText中的表情
EmojiconsFragment.backspace(etBottom);
}
@Override
public void onEmojiconClicked(Emojicon emojicon) {
//选中表情,在EditText中显示
EmojiconsFragment.input(etBottom, emojicon);
}
}
最近项目挺忙,只能抽空弄个小Demo记录自己如何集成Emoji,不多说,又要去撸代码了~~
Github源码下载
更多推荐
所有评论(0)