Android編程實(shí)現(xiàn)QQ表情的發(fā)送和接收完整實(shí)例(附源碼)
本文實(shí)例講述了Android編程實(shí)現(xiàn)QQ表情的發(fā)送和接收。分享給大家供大家參考,具體如下:
在自己做一個(gè)聊天應(yīng)用練習(xí)的時(shí)候,需要用到表情,于是就想著模仿一下QQ表情,圖片資源完全copy的QQ.apk,解壓就可以得到,這里不細(xì)說(shuō)。
下面將該應(yīng)用中的表情模塊功能抽離出來(lái),以便自己以后復(fù)習(xí)回顧。。
先看一下效果圖:
首先進(jìn)入界面:(完全仿照QQ)
點(diǎn)擊一下上面的表情圖標(biāo):
選擇一些表情,輸入一些文字混合:
點(diǎn)擊發(fā)送:
可以看到文字和表情圖片都一起顯示出來(lái)了。
下面列出一些關(guān)鍵代碼:
表情工具類ExpressionUtil:
public class ExpressionUtil { /** * 對(duì)spanableString進(jìn)行正則判斷,如果符合要求,則以表情圖片代替 * @param context * @param spannableString * @param patten * @param start * @throws SecurityException * @throws NoSuchFieldException * @throws NumberFormatException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void dealExpression(Context context,SpannableString spannableString, Pattern patten, int start) throws SecurityException, NoSuchFieldException, NumberFormatException, IllegalArgumentException, IllegalAccessException { Matcher matcher = patten.matcher(spannableString); while (matcher.find()) { String key = matcher.group(); if (matcher.start() < start) { continue; } Field field = R.drawable.class.getDeclaredField(key); int resId = Integer.parseInt(field.get(null).toString()); //通過(guò)上面匹配得到的字符串來(lái)生成圖片資源id if (resId != 0) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId); ImageSpan imageSpan = new ImageSpan(bitmap); //通過(guò)圖片資源id來(lái)得到bitmap,用一個(gè)ImageSpan來(lái)包裝 int end = matcher.start() + key.length(); //計(jì)算該圖片名字的長(zhǎng)度,也就是要替換的字符串的長(zhǎng)度 spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); //將該圖片替換字符串中規(guī)定的位置中 if (end < spannableString.length()) { //如果整個(gè)字符串還未驗(yàn)證完,則繼續(xù)。。 dealExpression(context,spannableString, patten, end); } break; } } } /** * 得到一個(gè)SpanableString對(duì)象,通過(guò)傳入的字符串,并進(jìn)行正則判斷 * @param context * @param str * @return */ public static SpannableString getExpressionString(Context context,String str,String zhengze){ SpannableString spannableString = new SpannableString(str); Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE); //通過(guò)傳入的正則表達(dá)式來(lái)生成一個(gè)pattern try { dealExpression(context,spannableString, sinaPatten, 0); } catch (Exception e) { Log.e("dealExpression", e.getMessage()); } return spannableString; } }
在顯示聊天頁(yè)面的list的適配器中,我們需要做如下的顯示,即調(diào)用上面工具類的方法:
SimpleChatAdapter中的內(nèi)部類ViewHolder:
private class ViewHolder{ RelativeLayout chat_layout; ImageView image; TextView text; public ViewHolder(View convertView){ chat_layout=(RelativeLayout) convertView.findViewById(R.id.team_singlechat_id_listiteam); image=(ImageView) convertView.findViewById(R.id.team_singlechat_id_listiteam_headicon); text=(TextView) convertView.findViewById(R.id.team_singlechat_id_listiteam_message); } public void setData(MessageInfo msg){ RelativeLayout.LayoutParams rl_chat_left=((RelativeLayout.LayoutParams)chat_layout.getLayoutParams()); RelativeLayout.LayoutParams rl_tv_msg_left=((RelativeLayout.LayoutParams)text.getLayoutParams()); RelativeLayout.LayoutParams rl_iv_headicon_left=((RelativeLayout.LayoutParams)image.getLayoutParams()); if(!DicqConstant.DEFAULTMAC.equalsIgnoreCase(msg.getUsermac())){ //根據(jù)本地的mac地址來(lái)判斷該條信息是屬于本人所說(shuō)還是對(duì)方所說(shuō) //如果是自己說(shuō)的,則顯示在右邊;如果是對(duì)方所說(shuō),則顯示在左邊 rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,-1); rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,0); rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,-1); rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,0); rl_tv_msg_left.addRule(RelativeLayout.RIGHT_OF,R.id.team_singlechat_id_listiteam_headicon); rl_tv_msg_left.addRule(RelativeLayout.LEFT_OF,0); text.setBackgroundResource(R.drawable.balloon_l_selector); }else{ rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,0); rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,-1); rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,0); rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,-1); rl_tv_msg_left.addRule(RelativeLayout.RIGHT_OF,0); rl_tv_msg_left.addRule(RelativeLayout.LEFT_OF,R.id.team_singlechat_id_listiteam_headicon); text.setBackgroundResource(R.drawable.balloon_r_selector); } image.setImageResource(PrortaitUtils.conversionIdToRes(msg.getProtrait())); //設(shè)置頭像 String str = msg.getMsg(); //消息具體內(nèi)容 String zhengze = "f0[0-9]{2}|f10[0-7]"; //正則表達(dá)式,用來(lái)判斷消息內(nèi)是否有表情 try { SpannableString spannableString = ExpressionUtil.getExpressionString(context, str, zhengze); text.setText(spannableString); } catch (NumberFormatException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } } }
關(guān)于表情彈出框的實(shí)現(xiàn)如下:
MainActivity:
/** * 創(chuàng)建一個(gè)表情選擇對(duì)話框 */ private void createExpressionDialog() { builder = new Dialog(MainActivity.this); GridView gridView = createGridView(); builder.setContentView(gridView); builder.setTitle("默認(rèn)表情"); builder.show(); gridView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { Bitmap bitmap = null; bitmap = BitmapFactory.decodeResource(getResources(), imageIds[arg2 % imageIds.length]); ImageSpan imageSpan = new ImageSpan(MainActivity.this, bitmap); String str = null; if(arg2<10){ str = "f00"+arg2; }else if(arg2<100){ str = "f0"+arg2; }else{ str = "f"+arg2; } SpannableString spannableString = new SpannableString(str); spannableString.setSpan(imageSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); edit.append(spannableString); builder.dismiss(); } }); } /** * 生成一個(gè)表情對(duì)話框中的gridview * @return */ private GridView createGridView() { final GridView view = new GridView(this); List<Map<String,Object>> listItems = new ArrayList<Map<String,Object>>(); //生成107個(gè)表情的id,封裝 for(int i = 0; i < 107; i++){ try { if(i<10){ Field field = R.drawable.class.getDeclaredField("f00" + i); int resourceId = Integer.parseInt(field.get(null).toString()); imageIds[i] = resourceId; }else if(i<100){ Field field = R.drawable.class.getDeclaredField("f0" + i); int resourceId = Integer.parseInt(field.get(null).toString()); imageIds[i] = resourceId; }else{ Field field = R.drawable.class.getDeclaredField("f" + i); int resourceId = Integer.parseInt(field.get(null).toString()); imageIds[i] = resourceId; } } catch (NumberFormatException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Map<String,Object> listItem = new HashMap<String,Object>(); listItem.put("image", imageIds[i]); listItems.add(listItem); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.team_layout_single_expression_cell, new String[]{"image"}, new int[]{R.id.image}); view.setAdapter(simpleAdapter); view.setNumColumns(6); view.setBackgroundColor(Color.rgb(214, 211, 214)); view.setHorizontalSpacing(1); view.setVerticalSpacing(1); view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); view.setGravity(Gravity.CENTER); return view; }
完整實(shí)例代碼代碼點(diǎn)擊此處本站下載。
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- 基于Android開發(fā)支持表情的實(shí)現(xiàn)詳解
- Android開發(fā)技巧之像QQ一樣輸入文字和表情圖像
- Android自帶emoji表情的使用方法詳解
- 完整的Android表情功能處理方案
- Android編程開發(fā)實(shí)現(xiàn)TextView顯示表情圖像和文字的方法
- 詳解Android過(guò)濾emoji表情正則表達(dá)式
- android高仿微信表情輸入與鍵盤輸入代碼(詳細(xì)實(shí)現(xiàn)分析)
- Android EdText編輯框禁止輸入表情符號(hào)(使用正則表達(dá)式)
- Android輸入框添加emoje表情圖標(biāo)的實(shí)現(xiàn)代碼
- Android實(shí)現(xiàn)表情功能
相關(guān)文章
Android studio點(diǎn)擊跳轉(zhuǎn)WebView詳解
這篇文章主要為大家詳細(xì)介紹了Android studio點(diǎn)擊跳轉(zhuǎn)WebView的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Android實(shí)現(xiàn)從緩存中讀取圖片與異步加載功能類
這篇文章主要介紹了Android實(shí)現(xiàn)從緩存中讀取圖片與異步加載功能類,涉及Android針對(duì)緩存的操作及圖片異步加載相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-08-08Android 將 android view 的位置設(shè)為右下角的解決方法
Android 將 android view 的位置設(shè)為右下角的解決方法,需要的朋友可以參考一下2013-05-05Android Studio 3.6中使用視圖綁定替代 findViewById的方法
從 Android Studio 3.6 開始,視圖綁定能夠通過(guò)生成綁定對(duì)象來(lái)替代 findViewById,從而可以幫您簡(jiǎn)化代碼、移除 bug,并且從 findViewById 的模版代碼中解脫出來(lái),今天通過(guò)本文給大家介紹使用視圖綁定替代 findViewById的方法,感興趣的朋友一起看看吧2020-03-03Android自定義控件實(shí)現(xiàn)時(shí)鐘效果
這篇文章主要介紹了Android自定義控件實(shí)現(xiàn)時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12Android中關(guān)于相對(duì)布局RelativeLayout的技巧匯總
RelativeLayout是相對(duì)布局控件,以控件之間相對(duì)位置或相對(duì)父容器位置進(jìn)行排列。下面這篇文章主要給大家介紹了關(guān)于Android中相對(duì)布局RelativeLayout的一些技巧,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-02-02Android 字符串中某個(gè)字段可點(diǎn)擊和設(shè)置顏色的方法
在android開發(fā)中,我們時(shí)常會(huì)遇到對(duì)字符串中某些固定的字段實(shí)現(xiàn)可點(diǎn)擊和顏色的設(shè)置,現(xiàn)粘貼處我在開發(fā)中如何設(shè)置這些屬性的2017-07-07Android自定義View實(shí)現(xiàn)可以拖拽的GridView
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)可以拖拽的GridView,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫功能的實(shí)例代碼
這篇文章主要介紹了Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Android中Glide庫(kù)的使用小技巧總結(jié)
Glide是 Google推薦的圖片加載庫(kù),相信大家都不陌生,這篇文章主要給大家總結(jié)介紹了關(guān)于Android中Glide庫(kù)的使用小技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11