前言:今天无聊翻了翻之前做的一个IM程序,趁着午休时间将聊天表情部分代码摘出来记录一下。
所谓表情消息,其实就是一串特殊格式的字符串,记得之前QQ是可以手输表情的。我的思路是将图片与名字(也就是前面说的特殊格式的字符串)进行一一对应,利用ViewPager+GridView展示表情列表,点击某一表情获取表情名字,然后转为Bitmap后再转为ImageSpan插入到EditText中。
1、资源准备
将所需要的表情图片放在aeest资源下,我这里直接从项目中摘出来的,也可以自己手动添加,名字格式要保持一致
2、初始化
定义一个List,用于保存各个图片的名字
private void initStaticFaces() { try { staticFacesList = new ArrayList<String>(); String[] faces = getAssets().list("face/png"); for (int i = 0; i < faces.length; i++) { staticFacesList.add(faces[i]); } //去掉删除图片 staticFacesList.remove("emotion_del_normal.png"); } catch (Exception e) { e.printStackTrace(); } }
初始化数据后初始化Viewpager
//获取页数 private int getPagerCount() { int count = staticFacesList.size(); return count % (columns * rows - 1) == 0 ? count / (columns * rows - 1) : count / (columns * rows - 1) + 1; } //初始化ViewPager private void initViewPager() { for (int i = 0; i < getPagerCount(); i++) { views.add(viewPagerItem(i)); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(16, 16); mDotsLayout.addView(dotsItem(i), params); } FaceVPAdapter mVpAdapter = new FaceVPAdapter(views); mViewPager.setAdapter(mVpAdapter); mDotsLayout.getChildAt(0).setSelected(true); } private ImageView dotsItem(int position) { LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.dot_image, null); ImageView iv = layout.findViewById(R.id.face_dot); iv.setId(position); return iv; } private View viewPagerItem(int position) { LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.face_gridview, null);//表情布局 GridView gridview = layout.findViewById(R.id.chart_face_gv); /** * 注:因为每一页末尾都有一个删除图标,所以每一页的实际表情columns * rows - 1; 空出最后一个位置给删除图标 * */ List<String> subList = new ArrayList<String>(); subList.addAll(staticFacesList .subList(position * (columns * rows - 1), (columns * rows - 1) * (position + 1) > staticFacesList .size() ? staticFacesList.size() : (columns * rows - 1) * (position + 1))); /** * 末尾添加删除图标 * */ subList.add("emotion_del_normal.png"); FaceGVAdapter mGvAdapter = new FaceGVAdapter(subList, this); gridview.setAdapter(mGvAdapter); gridview.setNumColumns(columns); return gridview; }
3、添加事件处理
点击表情,将表情插入到EditText中(如果是删除则删掉EditText中最后一个表情),长按删除则清空EditText
gridview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { try { String png = ((TextView) ((LinearLayout) view).getChildAt(1)).getText().toString(); if (!png.contains("emotion_del_normal")) {// 如果不是删除图标 insert(getFace(png)); } else { delete(); } } catch (Exception e) { e.printStackTrace(); } } }); gridview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { String png = ((TextView) ((LinearLayout) view).getChildAt(1)).getText().toString(); if (!png.contains("emotion_del_normal")) {// 如果不是删除图标 } else { deleteAll(); } return false; } });
4、插入、删除以及清空
private void insert(CharSequence text) { int iCursorStart = Selection.getSelectionStart((input.getText())); int iCursorEnd = Selection.getSelectionEnd((input.getText())); if (iCursorStart != iCursorEnd) { input.getText().replace(iCursorStart, iCursorEnd, ""); } int iCursor = Selection.getSelectionEnd((input.getText())); input.getText().insert(iCursor, text); } private void delete() { if (input.getText().length() != 0) { int iCursorEnd = Selection.getSelectionEnd(input.getText()); int iCursorStart = Selection.getSelectionStart(input.getText()); if (iCursorEnd > 0) { if (iCursorEnd == iCursorStart) { if (isDeletePng(iCursorEnd)) { String st = "#[face/png/f_static_000.png]#"; input.getText().delete( iCursorEnd - st.length(), iCursorEnd); } else { input.getText().delete(iCursorEnd - 1, iCursorEnd); } } else { input.getText().delete(iCursorStart, iCursorEnd); } } } } private void deleteAll() { input.setText(""); }
5、效果图
6、demo地址