欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-03 11:52:58
什么是emoji表情 emoji表情是一种表情符号,在代码中它现在其实是一组遵循unicode的编码,即每一个表情符号都对应了一个unicode编码。更进一步说,emoj...

什么是emoji表情

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

首先你得先从网上收集一套emoji的unicode编码,例如这个网站emoji unicode tables
该网站上面给出了每个emoji表情的图片,描述,unicode编码的对照表,点击表中每一项emoji可看到如下所示:

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

红色框框就是我们要的值.在java中的unicode表示就是:”\ud83d\ude01”,该编码字符可以直接被android的textview和edittext控件识别成对应的emoji表情.

本次demo中展示了从 “\ud83d\ude00” - “\ud83c\udf7c”这216个emoji表情.

效果图如下:

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

关于emoji编码的存放和获取

由于有216个emoji编码字符串,因此我把它整理到一个json数组中,然后保存到assets目录下.
然后获取的话,通过如下代码方式获取:

/**
* 从assets目录下获取所有表情
*
* @return
*/
public string[] getemojis() {
 bufferedreader br = null;
 string emojis[] = null;
 try {
 inputstream is = mcontext.getassets().open("emoji.json");
 stringbuffer sb = new stringbuffer();
 br = new bufferedreader(new inputstreamreader(is));
 string line = null;
 while (null != (line = br.readline())) {
 sb.append(line).append("\r\n");
 }
 jsonarray emojiarray = new jsonarray(sb.tostring());
 if (null != emojiarray && emojiarray.length() > 0) {
 emojis = new string[emojiarray.length()];
 for (int i = 0; i < emojiarray.length(); i++) {
 emojis[i] = emojiarray.optstring(i);
 }
 }
 } catch (exception e) {
 e.printstacktrace();
 } finally {
 if (null != br) {
 try {
 br.close();
 } catch (ioexception e) {
 e.printstacktrace();
 }
 }
 }
 return emojis;
}

表情组设计

通过上面的效果图也可以看得出,216个emoji表情被分成了8组,每组27个emoji+1个删除按钮.
实现这个效果也很简单,就是通过viewpager来展示每一组emoji,而每一组emoji里面又是一个gridview控件,里面的item就是一个个的textview.

每一组emoji页面的创建代码如下:

/**
* 获取所有表情gridview页面的集合
*
* @return
*/
public list<view> getpagerlist() {
 list<view> pagers = null;
 string[] eachpageemojis = null;
 if (null != memojis && memojis.length > 0) {
 pagers = new arraylist<>();
 int pagecount = memojis.length / 27;//共8页表情
 for (int i = 0; i < pagecount; i++) {
 gridview gridview = new gridview(mcontext);
 gridview.setnumcolumns(7);
 gridview.setselector(new colordrawable(color.transparent));
 gridview.setcachecolorhint(color.transparent);
 gridview.setstretchmode(gridview.stretch_column_width);
 gridview.setgravity(gravity.center);
 eachpageemojis = new string[28];
 //总共216个表情字符,索引变化为:0-26,27-53,54-80,81-107,108-134,135-161,162-188,189-215
 system.arraycopy(memojis, i * 27, eachpageemojis, 0, 27);
 eachpageemojis[27] = "del";//第28是删除按钮,用特殊字符串表示
 gridview.setadapter(new emojigvadapter(mcontext, eachpageemojis));
 //点击表情监听
 gridview.setonitemclicklistener(new adapterview.onitemclicklistener() {
 @override
 public void onitemclick(adapterview<?> parent, view view, int position, long id) {
 //获取选中的表情字符
 string emoji = (string) parent.getadapter().getitem(position);
 if (null != memojiclicklistener) {
 memojiclicklistener.onclick(emoji);
 }
 }
 });
 pagers.add(gridview);
 }
 }
 return pagers;
}

mainactivity的布局和代码

主布局是一个垂直的线性布局,大体分2部分,表情面板和上面的视图界面

<?xml version="1.0" encoding="utf-8"?>
<linearlayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 >
 <!--显示表情的textview-->
 <textview
 android:id="@+id/tv_info"
 android:layout_width="match_parent"
 android:layout_height="0dp"
 android:layout_weight="1"
 android:padding="15dp"
 />
 <!--表情,输入框,发送-->
 <linearlayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

 <button
 android:id="@+id/btn_emoji"
 android:layout_width="55dp"
 android:layout_height="wrap_content"
 android:text="表情"/>

 <edittext
 android:id="@+id/edt_msg"
 android:layout_width="0dp"
 android:layout_height="match_parent"
 android:layout_weight="1"/>

 <button
 android:id="@+id/btn_send"
 android:layout_width="55dp"
 android:layout_height="wrap_content"
 android:text="发送"/>
 </linearlayout>
 <!--表情面板-->
 <framelayout
 android:id="@+id/fl_emoji"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:visibility="gone"
 >

 <android.support.v4.view.viewpager
 android:id="@+id/vp_emoji"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:paddingtop="10dp"
 />

 <linearlayout
 android:id="@+id/ll_point"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom"
 android:layout_marginbottom="10dp"
 android:gravity="center"
 android:orientation="horizontal"></linearlayout>

 </framelayout>
</linearlayout>

mainactivity代码如下:

public class mainactivity extends appcompatactivity {
 private static final string tag = "mainactivity";
 private button memojibtn, msendbtn;//表情按钮和发送按钮
 private edittext mmsgedt;//输入框
 private textview minfotv;//展示界面
 private viewpager memojivp;//表情viewpager
 private framelayout memojifl;//表情面板
 private linearlayout mvppointll;//表情viewpager指示器
 //输入法和表情平滑切换的辅助类
 private emotionkeyboardswitchhelper memotionkeyboardswitchhelper;

 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);
 memotionkeyboardswitchhelper = emotionkeyboardswitchhelper.with(this);
 initview();
 initlistener();
 }

 private void initlistener() {
 msendbtn.setonclicklistener(new view.onclicklistener() {
 @override
 public void onclick(view v) {
 minfotv.append(mmsgedt.gettext() + "\r\n");
 mmsgedt.settext("");
 }
 });
 memotionkeyboardswitchhelper.bind(minfotv, mmsgedt, memojibtn, memojifl);
 }

 private void initview() {
 memojibtn = (button) findviewbyid(r.id.btn_emoji);
 msendbtn = (button) findviewbyid(r.id.btn_send);
 mmsgedt = (edittext) findviewbyid(r.id.edt_msg);
 minfotv = (textview) findviewbyid(r.id.tv_info);
 memojivp = (viewpager) findviewbyid(r.id.vp_emoji);
 memojifl = (framelayout) findviewbyid(r.id.fl_emoji);
 mvppointll = (linearlayout) findviewbyid(r.id.ll_point);
 initviewpager();
 }

 /**
 * 设置viewpager表情
 */
 private void initviewpager() {
 emojivpadapter adapter = new emojivpadapter(this);
 memojivp.setadapter(adapter);
 //表情点击监听
 adapter.setonemojiclicklistener(new emojivpadapter.onemojiclicklistener() {
 @override
 public void onclick(string emoji) {
 if ("del".equals(emoji)) {
 //表示点击的是删除按钮
 keyevent event = new keyevent(keyevent.action_down, keyevent.keycode_del);
 mmsgedt.onkeydown(keyevent.keycode_del, event);
 } else {
 mmsgedt.append(emoji);
 }
 }
 });
 memojivp.setcurrentitem(0);
 //关联指示器点
 adapter.setupwithpagerpoint(memojivp, mvppointll);
 }


 @override
 public void onbackpressed() {
 if (memotionkeyboardswitchhelper.onbackpress()) {
 super.onbackpressed();
 }
 }
}

emoji viewpager

public class emojivpadapter extends pageradapter {
 private context mcontext;
 private string[] memojis;//216个表情字符
 private list<view> mpagers;//展示的页面
 private onemojiclicklistener memojiclicklistener;//表情点击监听接口

 public emojivpadapter(context ctx) {
 this.mcontext = ctx;
 this.memojis = getemojis();
 this.mpagers = getpagerlist();

 }

 @override
 public int getcount() {
 return null == mpagers ? 0 : mpagers.size();
 }

 @override
 public boolean isviewfromobject(view view, object object) {
 return view == object;
 }

 @override
 public object instantiateitem(viewgroup container, int position) {
 view view = mpagers.get(position);
 if (null != view) {
 container.addview(view);
 }
 return view;
 }

 @override
 public void destroyitem(viewgroup container, int position, object object) {
 container.removeview((view) object);
 }

 /**
 * 从assets目录下获取所有表情
 *
 * @return
 */
 public string[] getemojis() {
 bufferedreader br = null;
 string emojis[] = null;
 try {
 inputstream is = mcontext.getassets().open("emoji.json");
 stringbuffer sb = new stringbuffer();
 br = new bufferedreader(new inputstreamreader(is));
 string line = null;
 while (null != (line = br.readline())) {
 sb.append(line).append("\r\n");
 }
 jsonarray emojiarray = new jsonarray(sb.tostring());
 if (null != emojiarray && emojiarray.length() > 0) {
 emojis = new string[emojiarray.length()];
 for (int i = 0; i < emojiarray.length(); i++) {
 emojis[i] = emojiarray.optstring(i);
 }
 }
 } catch (exception e) {
 e.printstacktrace();
 } finally {
 if (null != br) {
 try {
 br.close();
 } catch (ioexception e) {
 e.printstacktrace();
 }
 }
 }
 return emojis;
 }

 /**
 * 获取所有表情gridview页面的集合
 *
 * @return
 */
 public list<view> getpagerlist() {
 list<view> pagers = null;
 string[] eachpageemojis = null;
 if (null != memojis && memojis.length > 0) {
 pagers = new arraylist<>();
 int pagecount = memojis.length / 27;//共8页表情
 for (int i = 0; i < pagecount; i++) {
 gridview gridview = new gridview(mcontext);
 gridview.setnumcolumns(7);
 gridview.setselector(new colordrawable(color.transparent));
 gridview.setcachecolorhint(color.transparent);
 gridview.setstretchmode(gridview.stretch_column_width);
 gridview.setgravity(gravity.center);
 eachpageemojis = new string[28];
 //总共216个表情字符,索引变化为:0-26,27-53,54-80,81-107,108-134,135-161,162-188,189-215
 system.arraycopy(memojis, i * 27, eachpageemojis, 0, 27);
 eachpageemojis[27] = "del";//第28是删除按钮,用特殊字符串表示
 gridview.setadapter(new emojigvadapter(mcontext, eachpageemojis));
 //点击表情监听
 gridview.setonitemclicklistener(new adapterview.onitemclicklistener() {
 @override
 public void onitemclick(adapterview<?> parent, view view, int position, long id) {
 //获取选中的表情字符
 string emoji = (string) parent.getadapter().getitem(position);
 if (null != memojiclicklistener) {
 memojiclicklistener.onclick(emoji);
 }
 }
 });
 pagers.add(gridview);
 }
 }
 return pagers;
 }

 /**
 * 关联指示器点
 *
 * @param viewpager
 * @param pointlayout
 */
 public void setupwithpagerpoint(viewpager viewpager, final linearlayout pointlayout) {
 //初始表情指示器
 int pagecount = getcount();
 for (int i = 0; i < pagecount; i++) {
 imageview point = new imageview(mcontext);
 point.setimageresource(r.drawable.shape_vp_dot_unselected);
 linearlayout.layoutparams params = new linearlayout.layoutparams(-2, -2);
 params.rightmargin = (int) mcontext.getresources().getdimension(r.dimen.dp10);
 if (i == 0) {
 point.setimageresource(r.drawable.shape_vp_dot_selected);
 }
 pointlayout.addview(point, params);
 }
 viewpager.addonpagechangelistener(new viewpager.onpagechangelistener() {
 @override
 public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) {

 }

 @override
 public void onpageselected(int position) {
 //切换指示器
 if (null != pointlayout && pointlayout.getchildcount() > 0) {
 for (int i = 0; i < pointlayout.getchildcount(); i++) {
 ((imageview) pointlayout.getchildat(i)).setimageresource(r.drawable.shape_vp_dot_unselected);
 }
 ((imageview) pointlayout.getchildat(position)).setimageresource(r.drawable.shape_vp_dot_selected);
 }
 }

 @override
 public void onpagescrollstatechanged(int state) {

 }
 });
 }

 /**
 * 表情点击监听器
 */
 public interface onemojiclicklistener {
 void onclick(string emoji);
 }

 public void setonemojiclicklistener(onemojiclicklistener l) {
 this.memojiclicklistener = l;
 }
}

emoji gridview

public class emojigvadapter extends baseadapter {
 private context mcontext;
 private string[] memojis;

 public emojigvadapter(context context, string[] eachpageemojis) {
 this.mcontext = context;
 this.memojis = eachpageemojis;
 }

 @override
 public int getcount() {
 return null == memojis ? 0 : memojis.length;
 }

 @override
 public string getitem(int position) {
 return null == memojis ? "" : memojis[position];
 }

 @override
 public long getitemid(int position) {
 return position;
 }

 @override
 public view getview(int position, view convertview, viewgroup parent) {
 viewholder holder = null;
 if (null == convertview) {
 holder = new viewholder();
 convertview = view.inflate(mcontext, r.layout.item_emoji, null);
 holder.emojitv = (textview) convertview.findviewbyid(r.id.tv_emoji);
 convertview.settag(holder);
 } else {
 holder = (viewholder) convertview.gettag();
 }
 if (position == 27) {
 //第28个显示删除按钮
 holder.emojitv.setbackgroundresource(r.drawable.ic_emojis_delete);
 framelayout.layoutparams lp = (framelayout.layoutparams) holder.emojitv.getlayoutparams();
 lp.bottommargin = (int) mcontext.getresources().getdimension(r.dimen.dp12);
 } else {
 holder.emojitv.settext(getitem(position));
 }
 return convertview;
 }

 private static class viewholder {
 private textview emojitv;
 }


}

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