前言:今天无聊翻了翻之前做的一个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地址