效果图:
开始编码:
1、添加依赖
compile 'io.github.rockerhieu:emojicon:1.4.1'
2、布局文件代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:emojicon="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<io.github.rockerhieu.emojicon.EmojiconTextView
android:id="@+id/txtEmojicon"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_weight="5"
android:lineSpacingExtra="9dp"
emojicon:emojiconAlignment="baseline"
emojicon:emojiconSize="20sp" />
<LinearLayout
android:id="@+id/ll_pl"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#ffffff"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="6dp">
<io.github.rockerhieu.emojicon.EmojiconEditText
android:id="@+id/editEmojicon"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="5"
android:background="@drawable/bg_input"
android:hint="输入表情"
android:lineSpacingExtra="9dp"
android:paddingLeft="7dp"
emojicon:emojiconSize="28sp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="0.0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/icon_sr_bq" />
<Button
android:id="@+id/bt_fs"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginRight="8dp"
android:background="#00ddcc"
android:text="发送"
android:textColor="#ffffff"
android:textSize="14sp" />
</LinearLayout>
<FrameLayout
android:id="@+id/emojicons"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4.2"
android:visibility="gone" />
</LinearLayout>
3、Activity代码:
public class EmojActivity extends AppCompatActivity implements View.OnClickListener, EmojiconGridFragment.OnEmojiconClickedListener, EmojiconsFragment.OnEmojiconBackspaceClickedListener {
// EmojiconTextView继承自AppCompatTextView,而AppCompatTextView继承自TextView
private EmojiconEditText mEditEmojicon;
private EmojiconTextView mTxtEmojicon;
private TextView tvShow;
private boolean hasClick;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emoj);
findViewById(R.id.imageView).setOnClickListener(this);
findViewById(R.id.bt_fs).setOnClickListener(this);
mEditEmojicon = (EmojiconEditText) findViewById(R.id.editEmojicon);
mEditEmojicon.setOnClickListener(this);
mTxtEmojicon = (EmojiconTextView) findViewById(R.id.txtEmojicon);
tvShow = (TextView) findViewById(R.id.tvShow);
setEmojiconFragment(false);
}
private void setEmojiconFragment(boolean useSystemDefault) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.emojicons, EmojiconsFragment.newInstance(useSystemDefault))
.commit();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.imageView: // 表情按钮
if (hasClick) {
findViewById(R.id.emojicons).setVisibility(View.GONE);
} else {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); //强制隐藏键盘
findViewById(R.id.emojicons).setVisibility(View.VISIBLE);
}
hasClick = !hasClick;
break;
case R.id.bt_fs: // 发送按钮
Toast.makeText(this, mTxtEmojicon.getText(), Toast.LENGTH_SHORT).show();
tvShow.setText(mTxtEmojicon.getText() + "" + mEditEmojicon.getText());
mTxtEmojicon.setText(mTxtEmojicon.getText() + "" + mEditEmojicon.getText());
mEditEmojicon.setText("");
break;
case R.id.editEmojicon: // 输入框
findViewById(R.id.emojicons).setVisibility(View.GONE);
hasClick = !hasClick;
break;
}
}
@Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(mEditEmojicon, emojicon);
}
@Override
public void onEmojiconBackspaceClicked(View v) {
EmojiconsFragment.backspace(mEditEmojicon);
}
@Override
public void onBackPressed() {
if(hasClick){
findViewById(R.id.emojicons).setVisibility(View.GONE);
hasClick = !hasClick;
}else {
super.onBackPressed();
}
}
}
使用到的图片:
bg_input.png
icon_sr_bq.png
emojicon表情在服务器端数据库中的存取方法
参考博客: https://blog.csdn.net/Kodoo/article/details/48548833
问题描述
最近做一个Android项目,需要用到评论的功能,于是就需要emoji表情来让评论更加生动,于是在Github上找到了一个开源emoji表情库emojicon,效果如下。但是在使用过程中出现了问题,出现了表情存到数据库之后变为空白,所以取出后也是空白的问题。
问题原因
emoji分为 softbank emoji 和 unicode emoji,由于目前 softbank emoji 已停止更新,所以大多数 emoji 为 unicode emoji,emojicon 也是如此。unicode emoji 是四个字节长度,格式类似于 \uD83D 之类。由于项目和数据库都是UTF-8编码,UTF-8 是变长编码,可能是2-4个字节,而 MySQL 数据库的普通 UTF-8 编码只有三个字节,所以会出现无法解析的情况。
解决方案
大致有以下几种方法解决:
- 更改数据库编码 (不推荐使用)
- 转化为三个字节的 softbank emoji (不推荐使用)
- 对 unicode 字符串进行加密解密 (推荐使用)
更改数据库编码
MySQL 版本 5.5.3 以上可以使用utf8mb4编码来进行存储,此编码支持4字节的 UTF-8 字符。但是这样做很可能会在其他地方出现不兼容的问题,且更改数据库编码对系统整体改动太大,不推荐使用。
转化为 三个字节的softbank emoji
如果要转化为 softbank emoji 的话,需要通过对照表将 unicode emoji 转化为 softbank emoji,工作量不小,而且新的表情并不支持,不推荐使用。
对unicode字符串进行加密解密
我采用了 Apache 的 commons-lang 包中的 StringEscapeUtils 类来对字符串进行加密解密:
//加密
mContent = StringEscapeUtils.escapeJava(emojiEditText.getText().toString());
//解密
mComment.setContent(StringEscapeUtils.unescapeJava(json.getJSONObject(i).getString("content")));
这样就可以在数据库中存储了,但是又出现了新问题,就是解密后的表情是 \uD83D 这样的 unicode 编码,而不是表情。
查询数据库后发现,数据库中存储的字符串为 \uD83D 的样式,推测是对 \u 加了转义字符后,将转义字符也一起存储到数据库中了,因此解码后还是 \uD83D 这样的格式。因此,在解码之前,我们需要将 \uD83D 替换为 \uD83D ,即:
// 解密
mComment.setContent(StringEscapeUtils.unescapeJava(json.getJSONObject(i).getString("content").replace("\\\\u","\\u")));
至此,emojicon表情可以完美的存取了。