当前位置: 首页 > 编程笔记 >

Android编写简单的聊天室应用

柯英奕
2023-03-14
本文向大家介绍Android编写简单的聊天室应用,包括了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软件编程有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 上一节我们用ws模块创建了一个WebSocket应用。但是它只能简单地响应ECHO: xxx消息,还属于Hello, world级别的应用。 要创建真正的WebSocket应用,首先,得有一个基于MVC的Web应用,也就是我们在前面用koa2和Nunjucks创建的Web,在此基础上,把WebSocket添加进来,才算完整。 因此,本节的目标是基于WebSocket创建一个在线聊天室。 首先,我们

  • 本文向大家介绍Android实现简单C/S聊天室应用,包括了Android实现简单C/S聊天室应用的使用技巧和注意事项,需要的朋友参考一下 Android的网络应用:简单的C/S聊天室,供大家参考,具体内容如下 服务器端:提供两个类 创建ServerSocket监听的主类:MyServer.java 负责处理每个Socket通信的线程类:ServerThread.java 客户端:是一个Andro

  • 本文向大家介绍Node.js制作简单聊天室,包括了Node.js制作简单聊天室的使用技巧和注意事项,需要的朋友参考一下 看了TCP的有关知识,写了个基于NET的聊天室。 运行截图: 终端: telnet 这里截取了两个网友 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 本文向大家介绍Python socket实现简单聊天室,包括了Python socket实现简单聊天室的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Python socket实现简单聊天室的具体代码,供大家参考,具体内容如下 服务端使用了select模块,实现了对多个socket的监控。客户端由于select在Windows下只能对socket使用,所以使用了多线程来实现对客户端输

  • 本文向大家介绍python实现简单多人聊天室,包括了python实现简单多人聊天室的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python实现多人聊天室的具体代码,供大家参考,具体内容如下 刚开始学习python,写了一个聊天室练练手。 Server.py client.py 运行时先启动服务端。进入聊天室先起一个昵称。服务端会向客户端发送当前聊天室内聊天人的列表。一个客户端发出

  • 问题内容: 我想知道为数千名用户编写聊天应用程序的正确方法是什么。 我只是感到困惑,我如何才能每秒使用AJAX或更少的方法来对服务器执行ping操作,并检查MySQL中是否有新记录等,并且服务器负载可以接受。 我目前正在考虑使用jQuery,PHP和MySQL进行编码。 请指教。您的帮助将不胜感激。 问题答案: 客户端 对于需要轮询服务器的任何程序,我建议使用WebSockets。 我写了一个非常