Android编写简单的聊天室应用

最近写了一个简单的聊天室应用,可以发送表情,更改头像这些功能。主要技术点就是怎样把表情图片放到textview等Ui控件中展示。这里废话不多说,下面是效果图:

这里主要讲下怎样把文本替换到表情,先说下思路,首先我们的图片是保存在本地资源目录drawable中而所有的资源文件都是R这个类来管理,所以我们可以利用正则表达式找出图片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进行正则判断,如果符合要求,则以表情图片代替
   *
   * @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,用一个ImageSpan来包装
        int end = matcher.start() + key.length(); // 计算该图片名字的长度,也就是要替换的字符串的长度
        spannableString.setSpan(imageSpan, matcher.start(), end,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 将该图片替换字符串中规定的位置中
        if (end < spannableString.length()) { // 如果整个字符串还未验证完,则继续。。
          matchExpression(context, spannableString, patten, end);
        }
        break;
      }
    }
  } 

  /**
   * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断
   *
   * @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); // 通过传入的正则表达式来生成一个pattern
    try {
      matchExpression(context, spannableString, sinaPatten, 0);
    } catch (Exception e) {
      Log.e("dealExpression", e.getMessage());
    }
    return spannableString;
  } 

}

下面是聊天记录列表的adapter,这里主要是动态的改变每个Item的布局来区分是自己还是他人的发言,具体源码如下:

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())) {
        // 根据本地的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())); // 设置头像
      } else {
        image.setImageResource(R.drawable.im);
      }
      String str = msg.getMessage(); // 消息具体内容
      try {
        SpannableString spannableString = ExpressionUtil
            .getExpressionString(context, str, CommonUtils.PATTERN);
        text.setText(spannableString);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  } 

}

源码下载:Android聊天室应用

以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android socket聊天室功能实现

    前提概要 笔者很久之前其实就已经学习过了socket,当然也是用socket做过了聊天室,但是觉得此知识点比较一般,并无特别难的技术点,于是也并未深究. 然而近期一个项目中对socket的使用却让笔者感觉socket强大无比,可以实现诸多功能. 个人Socket体验 项目主要有关智能家居,需要实现多台手机同时对灯进行操作(开或者关),主要需要实现以下几点: 1.进入界面时获取所有灯的状态. 2.一台手机改变了灯的状态,其他的手机上可以有所显示. 3.硬件上改变了灯的状态(手动开关灯),所有手机上

  • Android 基于Socket的聊天室实例

    Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信. Client A  发信息给 Client B ,  A的信息首先发送信息到服务器Server ,Server接受到信息后再把A的信息广播发送给所有的Clients 首先我们要在服务器建立一个ServerSocket ,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待

  • Android使用多线程进行网络聊天室通信

    TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信了.Java对基于TCP协议的网络通信提供了良好的封装,Java使用Socket对象来代表两端通信接口,并通过Socket产生IO流来进行网络通信. 下面的程序Demo是实现一个简单的C/S聊天室的应用,每个客户端该包含两条线程:一条负责生成主界面,响应用户动作,并将用户输入的数据写入Socket对应的输出流中:另一条

  • Android中基于XMPP协议实现IM聊天程序与多人聊天室

    简单的IM聊天程序 由于项目需要做一个基于XMPP协议的Android通讯软件.故开始研究XMPP. XMPP协议采用的是客户端-服务器架构,所有从一个客户端发到另一个客户端的消息和数据都必须经过XMPP服务器转发,而且支持服务器间DNS的路由,也就是说可以构建服务器集群,使不同的 服务器下的客户端也可以通信,XMPP的前身是一个开源组织制定的网络通信协议--Jabber,XMPP的核心是在网络上分片段发送XML流的协议,这个协议是XMPP的即时通讯指令的传递手段.       为了防止服务器间

  • Android编写简单的聊天室应用

    最近写了一个简单的聊天室应用,可以发送表情,更改头像这些功能.主要技术点就是怎样把表情图片放到textview等Ui控件中展示.这里废话不多说,下面是效果图: 这里主要讲下怎样把文本替换到表情,先说下思路,首先我们的图片是保存在本地资源目录drawable中而所有的资源文件都是R这个类来管理,所以我们可以利用正则表达式找出图片id包装成ImageSpan然后把ImageSpan放到SpannableString中,最后把SpannableString放入edittext中,下面是源码: pack

  • js编写简单的聊天室功能

    这个聊天室写的特别简易,比较适合刚开始学习js的同学借鉴,当然,写的不好,也希望诸位大神可以进行批评改正. 聊天室要求: 1.不能发空消息 2.敏感字***显示 3.图片替换 开心,尴尬 4.显示聊天内容和时间 5.每发一条信息,随机显示名称,先把一些名称定义到array里面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> &

  • Android使用Websocket实现聊天室

    最近的项目中要实现一个聊天的功能,类似于斗鱼TV的聊天室功能,与服务器端人商量后决定用WebSocket来做,但是在这之前我只知道Socket但是听都没有听过WebSocket,但是查看了相关的材料以后发现实现一个聊天室其实是很简单的!下面我们先来看看WebSocket. Autobahn|Android 是由Autobahn开发一个开源的Java/Android网络库,实现了WebSocket协议和Web应用程序消息传输协议来创建本地移动的WebSocket/ WAMP的客服端. WebSoc

  • 玩转NODE.JS(四)-搭建简单的聊天室的代码

    Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一些个教程使用它来搭建一个超级简单的聊天室. 初始化项目 在电脑里新建一个文件夹,叫做"chatroom",然后使用npm进行初始化: $ npm init 然后根据提示以及相关信息一步一步输入,当然也可以一路回车下去,之后会在项目里生成一个package.json文件,里面的信息如下: $ cat package.json { &q

  • GO使用socket和channel实现简单控制台聊天室

    使用socket和channel,实现简单控制台聊天室 这里使用socket和channel,演示在GO中如何编写一个简单网络程序 功能分析 聊天室主要功能:用户可以加入/离开聊天室:每个用户发送的消息,广播给所有人 聊天室分为客户端和服务端,客户端负责发送消息和打印服务器消息,服务器负责接收客户端消息,并广播给所有人 客户端可以使用telnet程序 服务端是需要实现的.需要实现的功能, 如何保存多个客户端的连接,管理连接的接入与断开 如何接收和广播客户端消息 实现思路 通过功能分析,拆分为聊天

  • ASP建立一个简单的聊天室

    经过一个阶段的asp学习,下面我们结合所学过的内容建立一个最简单的聊天室,虽然很简单,但是大家可以通过它来掌握一个聊天室建立的基本过程,并且可以不断的完善其功能. 下面介绍其主要步骤: 1,添加Global.asa文件里面的代码.这部分代码主要处理Application_onStart事件,在此事件中,定义了一个有15个元素的数据,并把它赋给了一个Application对象的属性.Global.asa文件的内容如下. <SCRIPT LANGUAGE="VBScript" RUN

  • Android编写简单的网络爬虫

    一.网络爬虫的基本知识 网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念.爬虫如何遍历网络呢,互联网可以看做是一张大图,每个页面看做其中的一个节点,页面的连接看做是有向边.图的遍历方式分为宽度遍历和深度遍历,但是深度遍历可能会在深度上过深的遍历或者陷入黑洞.所以,大多数爬虫不采用这种形式.另一方面,爬虫在按照宽度优先遍历的方式时候,会给待遍历的网页赋予一定优先级,这种叫做带偏好的遍历. 实际的爬虫是从一系列的种子链接开始.种子链接是起始节点,种子页面的超链接指向的页面是

  • Java基于UDP协议实现简单的聊天室程序

    最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. 先看一下效果: 实现的效果可以说是非常非常简单,但还是可以简单的看到一个实现原理.  "聊天室001"的用户,小红和小绿相互聊了两句,"聊天室002"的小黑无人理会,在一旁寂寞着. 看一下代码实现: 1.首先是消息服务器的实现,功能很简单: •将客户端的信息(进入了哪一

  • c#基于WinForm的Socket实现简单的聊天室 IM

    1:什么是Socket 所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象. 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制. 从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口. 2:客服端和服务端的通信简单流程 3:服务端Code: using System; using System.Collections.Generic; using Sys

  • Java实现简单局域网聊天室

    本文实例为大家分享了Java实现简单局域网聊天室的具体代码,供大家参考,具体内容如下 Java 的Socket编程: 1.TCP协议是面向连接的.可靠的.有序的.以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道,在连接中进行大量数据的传输,效率会稍低 2.Java中基于TCP协议实现网络通信的类 客户端的Socket类 服务器端的ServerSocket类 3.Socket通信的步骤 ① 创建ServerSocket和Socket ② 打开连接到Socket的输入/输出流 ③

随机推荐