Android客户端的表情实现------来自王阳

3 篇文章 0 订阅
1 篇文章 0 订阅


客户端表情的研究与实现


这两天研究了一些关于类似微信的表情发送的实现,目前发现的实现方法是:在聊天界面上添加一个ImageButton,并添加一个GridView。为ImageButton添加点击事件,当点击时弹出GridView,也就是默认情况下GridView的visible属性是INVISIBLE,再次点击隐藏。GridView即表情选择界面,上面每一个Item都是一个表情,每个表情都是/res文件夹下的一个图片,可以通过R.drawable.imagename进行访问。表情与GridView的关联是通过继承BaseAdapter的GridAdapter进行的。为GridView添加OnItemClickListener监听,为用户点击表情后插入表情作出相应的响应。主要思想叙述完了,下面上代码。

首先是相关的变量和类的声明:

private Emotions emotionClass; private Map<String, String> emotionsMap; private ImageButton emotion; private int[] emotion_array; private GridView emotionView;

之后是相关的变量初始化和监听器初始化:

emotion = (ImageButton) findViewById(R.id.btn_emotion); emotion.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO 自动生成的方法存根 displayEmotionSelectView(); } }); emotionView = (GridView) findViewById(R.id.emotion_grid_view); emotionView.setAdapter(new GridAdapter(ScreenChat.this)); // 选择表情 emotionView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { emotionsMap = emotionClass.getEmotionsList_image(); addEmotionImageToEditText(position); } }); mEtCompose = (EditText) findViewById(R.id.screen_chat_editText_compose);

GridAdapter:

private class GridAdapter extends BaseAdapter { public GridAdapter(Context context) { } public int getCount() { // TODO Auto-generated method stub return emotion_array.length; } public Object getItem(int position) { // TODO Auto-generated method stub return null; } public long getItemId(int position) { // TODO Auto-generated method stub return 0; } public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(ScreenChat.this); imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setLayoutParams(new GridView.LayoutParams(20, 20)); } else { imageView = (ImageView) convertView; } imageView.setBackgroundResource(emotion_array[position]); return imageView; } }

两个主要方法:
显示表情选择界面:

private void displayEmotionSelectView() { /* * if(!isWrite){ * btnSendOrChange.setBackgroundResource(R.drawable.voice_weixin_own); * btnVoice.setVisibility(View.GONE); * contentEditText.setVisibility(View.VISIBLE); isWrite = true; } */ if (emotionView.getVisibility() != View.VISIBLE) { // 隐藏软键盘 if (ScreenChat.this.getCurrentFocus() != null) { ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) .hideSoftInputFromWindow(ScreenChat.this .getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } /* * //隐藏expand列表----"+"号控件,可以添加图片等聊天信息,待实现 * if(expandView.getVisibility() == View.VISIBLE) * expandView.setVisibility(View.GONE); */ // 显示表情 emotionView.setVisibility(View.VISIBLE); /* * if(chatList != null && chatList.size()>1){ new Handler().post(new * Runnable() { * * @Override public void run() { * chatListView.setSelection(chatList.size() - 1); } }); } */ } else { // 隐藏表情 emotionView.setVisibility(View.GONE); } }

将表情添加到聊天文本编辑器中:

public void addEmotionImageToEditText(int position) { Drawable drawable = getResources().getDrawable(emotion_array[position]); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); String text = emotionsMap.get(emotion_array[position] + ""); int cursor = mEtCompose.getSelectionStart(); String textContent = mEtCompose.getText().toString(); String head = textContent.substring(0, cursor); String tail = textContent.substring(cursor, textContent.length()); String content = head + "[" + text + "]" + tail; mEtCompose.setText(content); Editable editable = mEtCompose.getText(); Selection.setSelection(editable, cursor + (text.length() + 2)); // textAutoLink.addEmotionSpan(ScreenChat.this, content, mEtCompose); }

表情界面,仅仅是实现了可以向聊天输入框中添加文字化的表情,而且并没有实现发送。今天研究了一下,如何进行发送。
主要思想是:通过java的SpannableString可以向Text文本中绑定或者说添加图片,这样就可以通过textView.setText(spannableText)方法使得聊天中出现图片了。
下面上代码,大家可能注意到了昨天代码中的一行注释掉的代码,这就是今天的关键。
首先,增加了一些变量。

private static Context screenChatContext;

private Emotions emotionClass; private Map<String, String> emotionsMap; private ImageButton emotion; private int[] emotion_array; private GridView emotionView; private static EmotionUtils emotionUtils;

记得对这些变量初始化哦,否则会报空指针异常。

screenChatContext=ScreenChat.this; emotionUtils = new EmotionUtils(); emotionClass = new Emotions(); emotion_array = emotionClass.emotion; emotion = (ImageButton) findViewById(R.id.btn_emotion);

emotionView = (GridView) findViewById(R.id.emotion_grid_view);

然后是在聊天编辑框中可以显示表情:

public void addEmotionImageToEditText(int position) { Drawable drawable = getResources().getDrawable(emotion_array[position]); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); String text = emotionsMap.get(emotion_array[position] + ""); int cursor = mEtCompose.getSelectionStart(); String textContent = mEtCompose.getText().toString(); String head = textContent.substring(0, cursor); String tail = textContent.substring(cursor, textContent.length()); String content = head + "[" + text + "]" + tail; mEtCompose.setText(content); Editable editable = mEtCompose.getText(); Selection.setSelection(editable, cursor + (text.length() + 2)); emotionUtils.addEmotionSpan(ScreenChat.this, content, mEtCompose);//就是它了! }

我们来看一看EmotionUtils这个类:

public void addEmotionSpan(Context context, String str, EditText textView) { int cursor = textView.getSelectionStart(); textView.setText(getEmotionSpannable(context, str)); // 设定TextView话题和url和好友 连接 Editable editable = textView.getText(); Selection.setSelection(editable, cursor); strarray = null; } public SpannableString getEmotionSpannable(Context context, String str){ SpannableString ss = new SpannableString(str); String content = str; int i = 0; int starts = 0; int end = 0; while (i < content.length()) {//此处为了获得文字化的表情的text starts = content.indexOf("[", i); if (starts == -1) { break; } end = content.indexOf("]", starts); if (end == -1) { break; } if(end <= starts){ if (starts >= i) { i = starts; } i++; break; }

//下面把得到的文字化表情text换成图片 String phrase = content.substring(starts + 1, end); emotion = new Emotions(); emotions_map = emotion.getEmotionsList_text(); if (emotions_map.get(phrase) != null) { try { Drawable drawable = context.getResources().getDrawable( emotions_map.get(phrase)); if (drawable != null) { drawable.setBounds(0, DisplayUtils.dip2px(context, 5f), DisplayUtils.dip2px(context, 20f), DisplayUtils.dip2px(context, 25f)); ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE); ss.setSpan(span, starts, end + 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } } if (end >= i) { i = end; } i++; } return ss; }

以上就是通过一个SpanableString来显示表情啦,ss就是最终返回的含有表情图片的String文字,可以通过setText()方法传递给编辑框EditText。
这样就完成了在编辑框中显示表情了。不过这样显然不够,因为此时发送和接收的仍然是文字化的表情,因此,也需要把它们都变成图片。发送和接收表情显示在聊天界面的ListView中,而ListView是通过与它绑定的Adapter控制自己的内容的,因此,需要修改Adapter。

static class ScreenChatAdapter extends BaseAdapter implements Observer {

/.../ //省略其他方法

@Override

public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; final NgnHistoryEvent event = (NgnHistoryEvent) getItem(position); if (event == null) { return null; } if (view == null) { switch (event.getMediaType()) { case Audio: case AudioVideo: case FileTransfer: default: Log.e(TAG, "Invalid media type"); return null; case SMS: break; } } final NgnHistorySMSEvent SMSEvent = (NgnHistorySMSEvent) event; final String content = SMSEvent.getContent(); final boolean bIncoming = SMSEvent.getStatus() == StatusType.Incoming; SimpleDateFormat sdformat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");// 24小时制 if (bIncoming) { view = mInflater.inflate(R.layout.chatting_item_msg_text_left, null); TextView tvSendTime = (TextView) view .findViewById(R.id.tv_sendtime); // TextView tvUserName = (TextView) // convertView.findViewById(R.id.tv_username); TextView tvContent = (TextView) view .findViewById(R.id.tv_chatcontent); tvSendTime .setText(DateTimeUtils.getFriendlyDateString(new Date( SMSEvent.getStartTime()))); SpannableString spannableChatContent=emotionUtils.getEmotionSpannable(screenChatContext, content); tvContent.setText(content == null ? NgnStringUtils.emptyValue() : spannableChatContent); } else { view = mInflater.inflate(R.layout.chatting_item_msg_text_right, null); TextView tvSendTime = (TextView) view .findViewById(R.id.tv_sendtime); // TextView tvUserName = (TextView) // convertView.findViewById(R.id.tv_username); TextView tvContent = (TextView) view .findViewById(R.id.tv_chatcontent); tvSendTime .setText(DateTimeUtils.getFriendlyDateString(new Date( SMSEvent.getStartTime()))); SpannableString spannableChatContent=emotionUtils.getEmotionSpannable(screenChatContext, content); tvContent.setText(content == null ? NgnStringUtils.emptyValue() : spannableChatContent); } return view; }

}

以上主要修改的是getView()方法,这个方法返回每一个Item,而修改EditText的setText()方法中的参数,将原来的纯文本改成带图片的文本就可以了,即将String类型改为SpannableString。
嗯,这样就好了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值