Android編寫簡單的聊天室應(yīng)用
最近寫了一個(gè)簡單的聊天室應(yīng)用,可以發(fā)送表情,更改頭像這些功能。主要技術(shù)點(diǎn)就是怎樣把表情圖片放到textview等Ui控件中展示。這里廢話不多說,下面是效果圖:

這里主要講下怎樣把文本替換到表情,先說下思路,首先我們的圖片是保存在本地資源目錄drawable中而所有的資源文件都是R這個(gè)類來管理,所以我們可以利用正則表達(dá)式找出圖片id包裝成ImageSpan然后把ImageSpan放到SpannableString中,最后把SpannableString放入edittext中,下面是源碼:
package com.coreandroid.util;
import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.Log;
import com.coreandroid.chart.R;
public class ExpressionUtil {
/**
* 對spanableString進(jìn)行正則判斷,如果符合要求,則以表情圖片代替
*
* @param context
* @param spannableString
* @param patten
* @param start
*/
public static void matchExpression(Context context,
SpannableString spannableString, Pattern patten, int start)
throws Exception {
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 = field.getInt(null); // 通過上面匹配得到的字符串來生成圖片資源id
if (resId != 0) {
ImageSpan imageSpan = new ImageSpan(context, resId); // 通過圖片資源id來得到bitmap,用一個(gè)ImageSpan來包裝
int end = matcher.start() + key.length(); // 計(jì)算該圖片名字的長度,也就是要替換的字符串的長度
spannableString.setSpan(imageSpan, matcher.start(), end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 將該圖片替換字符串中規(guī)定的位置中
if (end < spannableString.length()) { // 如果整個(gè)字符串還未驗(yàn)證完,則繼續(xù)。。
matchExpression(context, spannableString, patten, end);
}
break;
}
}
}
/**
* 得到一個(gè)SpanableString對象,通過傳入的字符串,并進(jìn)行正則判斷
*
* @param context
* @param str
* @return SpannableString
*/
public static SpannableString getExpressionString(Context context,
String str, String zhengze) {
SpannableString spannableString = new SpannableString(str);
Pattern sinaPatten = Pattern.compile(zhengze); // 通過傳入的正則表達(dá)式來生成一個(gè)pattern
try {
matchExpression(context, spannableString, sinaPatten, 0);
} catch (Exception e) {
Log.e("dealExpression", e.getMessage());
}
return spannableString;
}
}
下面是聊天記錄列表的adapter,這里主要是動(dòng)態(tài)的改變每個(gè)Item的布局來區(qū)分是自己還是他人的發(fā)言,具體源碼如下:
package com.coreandroid.adapter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.content.Context;
import android.text.SpannableString;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.coreandroid.chart.R;
import com.coreandroid.entity.MessageInfo;
import com.coreandroid.util.CommonUtils;
import com.coreandroid.util.ExpressionUtil;
public class ChartListAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private List<MessageInfo> data;
private DateFormat df;
public ChartListAdapter(Context context, List<MessageInfo> data) {
super();
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.chart_list_item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.setData((MessageInfo) getItem(position));
return convertView;
}
private class ViewHolder {
private ImageView image;
private TextView text;
private TextView title;
private RelativeLayout rl;
public ViewHolder(View convertView) {
image = (ImageView) convertView
.findViewById(R.id.chart_list_item_headicon);
text = (TextView) convertView
.findViewById(R.id.chart_list_item_message);
title = (TextView) convertView
.findViewById(R.id.chart_list_item_title);
rl = (RelativeLayout) convertView
.findViewById(R.id.rl_chart_list_bottom);
}
public void setData(MessageInfo msg) {
RelativeLayout.LayoutParams rl_tv_msg_left = (RelativeLayout.LayoutParams) text
.getLayoutParams();
RelativeLayout.LayoutParams rl_iv_headicon_left = (RelativeLayout.LayoutParams) image
.getLayoutParams();
RelativeLayout.LayoutParams rl_tv_title = (RelativeLayout.LayoutParams) title
.getLayoutParams();
RelativeLayout.LayoutParams rl_buttom = (RelativeLayout.LayoutParams) rl
.getLayoutParams();
if (!CommonUtils.getDeviceId().equalsIgnoreCase(msg.getUsermac())) {
// 根據(jù)本地的mac地址來判斷該條信息是屬于本人所說還是對方所說
// 如果是自己說的,則顯示在右邊;如果是對方所說,則顯示在左邊
rl_buttom.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rl_tv_title.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
rl_tv_title.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
rl_tv_title.addRule(RelativeLayout.BELOW,
R.id.rl_chart_list_bottom);
rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
rl_tv_msg_left.addRule(RelativeLayout.RIGHT_OF,
R.id.chart_list_item_headicon);
text.setBackgroundResource(R.drawable.incoming);
String titleStr = msg.getUsermac() + "-"
+ df.format(new Date());
title.setText(titleStr);
} else {
rl_buttom.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rl_tv_title.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
rl_tv_title.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
rl_tv_title.addRule(RelativeLayout.BELOW,
R.id.rl_chart_list_bottom);
rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
rl_tv_msg_left.addRule(RelativeLayout.LEFT_OF,
R.id.chart_list_item_headicon);
text.setBackgroundResource(R.drawable.outgoing);
String titleStr = df.format(new Date()) + "-"
+ msg.getUsermac();
title.setText(titleStr);
}
if (!TextUtils.isEmpty(msg.getHeadImage())) {
image.setImageBitmap(CommonUtils.strConvertBitmap(msg
.getHeadImage())); // 設(shè)置頭像
} else {
image.setImageResource(R.drawable.im);
}
String str = msg.getMessage(); // 消息具體內(nèi)容
try {
SpannableString spannableString = ExpressionUtil
.getExpressionString(context, str, CommonUtils.PATTERN);
text.setText(spannableString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
源碼下載:Android聊天室應(yīng)用
以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)Android軟件編程有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)簡單C/S聊天室應(yīng)用
- Android實(shí)現(xiàn)C/S聊天室
- Android Socket通信實(shí)現(xiàn)簡單聊天室
- Android使用Websocket實(shí)現(xiàn)聊天室
- Android使用多線程進(jìn)行網(wǎng)絡(luò)聊天室通信
- android socket聊天室功能實(shí)現(xiàn)
- Android 基于Socket的聊天室實(shí)例
- Android中基于XMPP協(xié)議實(shí)現(xiàn)IM聊天程序與多人聊天室
- Android文本視圖TextView實(shí)現(xiàn)聊天室效果
相關(guān)文章
解決Android Studio突然不顯示logcat日志的問題
這篇文章主要介紹了解決Android Studio突然不顯示logcat日志的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
設(shè)置Android設(shè)備WIFI在休眠時(shí)永不斷開的代碼實(shí)現(xiàn)
這篇文章主要介紹了設(shè)置Android設(shè)備WIFI在休眠時(shí)永不斷開的代碼實(shí)現(xiàn),需要的朋友可以參考下2014-07-07
android編程開發(fā)之全屏和退出全屏的實(shí)現(xiàn)方法
這篇文章主要介紹了android編程開發(fā)之全屏和退出全屏的實(shí)現(xiàn)方法,以實(shí)例形式較為詳細(xì)的分析了Android全屏及退出全屏的頁面布局與功能實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Android自定義控件實(shí)現(xiàn)可左右滑動(dòng)的導(dǎo)航條
這篇文章主要介紹了Android自定義控件實(shí)現(xiàn)可左右滑動(dòng)的導(dǎo)航條,能響應(yīng)快速滑動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Android AIDL和遠(yuǎn)程Service調(diào)用示例代碼
本文主要介紹Android AIDL和遠(yuǎn)程Service,這里詳細(xì)介紹了相關(guān)知識(shí),并附實(shí)例代碼和實(shí)現(xiàn)效果圖,有興趣的朋友參考下2016-08-08
基于Android中手勢交互的實(shí)現(xiàn)方法
本篇文章是對Android中手勢交互的實(shí)現(xiàn)進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05
Android手機(jī)信號強(qiáng)度檢測詳細(xì)介紹
這篇文章主要介紹了Android手機(jī)信號強(qiáng)度檢測的相關(guān)資料,android定義了2種信號單位:dBm和asu。具體兩種的關(guān)系本文給大家介紹非常詳細(xì),需要的朋友可以參考下2016-11-11
聲網(wǎng)SDK教程Android UIKit 實(shí)時(shí)視頻通話添加自定義背景
這篇文章主要為大家介紹了聲網(wǎng)SDK教程Android UIKit 實(shí)時(shí)視頻通話添加自定義背景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Android解決viewpager嵌套滑動(dòng)沖突并保留側(cè)滑菜單功能
這篇文章主要介紹了 解決viewpager嵌套滑動(dòng)沖突,并保留側(cè)滑菜單功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06

