设置界面没什么好说的,无非也就是加了个对话框来二次提醒用户,现在来讲讲聊天界面。

聊天界面初始化时会得到一个参数,就是对方的id,并设置在标题栏的位置,此界面也是使用RecyclerView来展示聊天消息。

首先为RecyclerView添加布局管理器(线性布局),并且为其添加适配器,写适配器之前先写类,消息类展示:

public class Msg extends LitePalSupport {
public static final int TYPE_RECEIVED = 0; // 接收消息
public static final int TYPE_SENT = 1; // 发送消息
private String Sender;
private String Receiver;
private String content;
private int type;
Msg(String content, int type) {
this.content = content;
this.type = type;
}
public static int getTypeReceived() {
return TYPE_RECEIVED;
}
public static int getTypeSent() {
return TYPE_SENT;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getSender() {
return Sender;
}
public void setSender(String sender) {
Sender = sender;
}
public String getReceiver() {
return Receiver;
}
public void setReceiver(String receiver) {
Receiver = receiver;
}
}

然后写适配器,用于RecyclerView的展示以及各种事件的处理,首先定义一个内部类ViewHolder,继承自RecyclerView.ViewHolder,用来缓存子项的各个实例,提高效率,其余的我都用注释进行标注了:

public class MsgAdapter extends RecyclerView.Adapter{
private ListmMsgList;
static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
// view表示父类的布局,用其获取子项
ViewHolder(View view) {
super(view);
leftLayout = view.findViewById(R.id.left_layout);
rightLayout = view.findViewById(R.id.right_layout);
leftMsg = view.findViewById(R.id.left_msg);
rightMsg = view.findViewById(R.id.right_msg);
}
}
MsgAdapter(ListmsgList) {
mMsgList = msgList;
}
/**
* 创建 ViewHolder 加载 RecycleView 子项的布局
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent, false);
return new ViewHolder(view);
}
/**
* 为 RecycleView 子项赋值
* 赋值通过 position 判断子项位置
* 当子项进入界面时执行
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Msg msg = mMsgList.get(position);
if (msg.getType() == Msg.TYPE_RECEIVED) {
// 如果是收到的消息,则显示左边的消息布局,将右边的消息布局隐藏
holder.leftLayout.setVisibility(View.VISIBLE);
holder.rightLayout.setVisibility(View.GONE);
holder.leftMsg.setText(msg.getContent());
} else if (msg.getType() == Msg.TYPE_SENT) {
// 如果是发出的消息,则显示右边的消息布局,将左边的消息布局隐藏
holder.rightLayout.setVisibility(View.VISIBLE);
holder.leftLayout.setVisibility(View.GONE);
holder.rightMsg.setText(msg.getContent());
}
}
//返回子项个数
@Override
public int getItemCount() {
return mMsgList.size();
}
}

RecyclerView介绍完之后,返回来继续介绍聊天界面,初始化的时候也是先读取数据库,这里我做了限制,只查询出最近的50条聊天记录:

//读取数据库
private void read__db() {
msgList.clear();
msgL = LitePal.where("Sender = ? and Receiver = ?;",username,friend).find(Msg.class);
int count = msgL.size();
//判断消息长度,最多从数据库读取50条消息
if(count > 0 && count <=50 ){
sel_50(0);
}else if(count > 50){
sel_50(count - 50);
}
// 当有新消息时,刷新ListView中的显示
adapter.notifyItemInserted(msgList.size() - 1);
// 将ListView定位到最后一行
msgRecyclerView.scrollToPosition(msgList.size() - 1);
}
//查询截取50条数据
private void sel_50(int i){
for (; i < msgL.size(); i++){
//加个异常
try{
Msg msgLi = new Msg(msgL.get(i).getContent(),msgL.get(i).getType());
msgList.add(msgLi);
}catch (Exception e) {}
}
}

初始化完毕,当用户点击发送按钮的时候使用BmobIMConversation的sendMessage方法进行发送消息(具体请参考官方文档):

send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//检查网络连接
if(!NetWork.isNetConnection(Main.this))
Toast.makeText(Main.this,"无网络连接!",Toast.LENGTH_SHORT).show();
else{
if(!MainActivity.isConnect)
Toast.makeText(Main.this,"连接服务器失败!",Toast.LENGTH_SHORT).show();
//网络正常
String content = inputText.getText().toString();
if (!"".equals(content)) {
final Msg ms = new Msg(content, Msg.TYPE_SENT);
//连接成功,发送消息
BmobIMUserInfo info =new BmobIMUserInfo();
info.setAvatar("填写接收者的头像");
info.setUserId(friend);
info.setName("填写接收者的名字");
ms.setReceiver(friend);
ms.setSender(MyUser.getUni());
Tips.Receiver = friend;
// BmobIMConversation conversationEntrance =
try{
BmobIM.getInstance().startPrivateConversation(info, new ConversationListener() {
@Override
public void done(BmobIMConversation c, BmobException e) {
if(e==null){
//在此跳转到聊天页面或者直接转化
mBmobIMConversation=BmobIMConversation.obtain(BmobIMClient.getInstance(),c);
BmobIMTextMessage msg =new BmobIMTextMessage();
msg.setContent(ms.getContent());
//发送消息
mBmobIMConversation.sendMessage(msg, new MessageSendListener() {
@Override
public void done(BmobIMMessage msg, BmobException e) {
if (e != null) {
Toast.makeText(Main.this, "发送失败", Toast.LENGTH_SHORT).show();
}else{
//添加消息
add(ms);
}
}
});
}else{
Toast.makeText(Main.this, "开启会话出错", Toast.LENGTH_SHORT).show();
}
}
});
}catch (Exception e){}
}
}
}
});

消息发送成功之后要进行本地数据库的更新,不光要更新消息列表,也要更新会话列表,使会话列表展示的是最新的消息:

//添加消息
public static void add(Msg msg){
if(msg.getType() == 1){
msgList.add(msg);
// 当有新消息时,刷新ListView中的显示
adapter.notifyItemInserted(msgList.size() - 1);
// 将ListView定位到最后一行
msgRecyclerView.scrollToPosition(msgList.size() - 1);
// 清空输入框中的内容
inputText.setText("");
}else if(msg.getReceiver().equals(friend)) {
msgList.add(msg);
adapter.notifyItemInserted(msgList.size() - 1);
msgRecyclerView.scrollToPosition(msgList.size() - 1);
}
//保存数据库
msg.save();
int len = msg.getContent().length();
ConList lis;
if(len > 15){
String show = msg.getContent().substring(0,12);
if(msg.getType() == 1)
lis = new ConList(friend,"我:"+show+"......");
else
lis = new ConList(friend,"对方:"+show+"......");
}else {
if(msg.getType() == 1)
lis = new ConList(friend,"我:"+msg.getContent());
else
lis = new ConList(friend,"对方:"+msg.getContent());
}
lis.save();
}

即时聊天APP(五) - 聊天界面的更多相关文章

  1. 即时通信系统中实现聊天消息加密,让通信更安全【低调赠送:C#开源即时通讯系统(支持广域网)——GGTalk4.5 最新源码】

    在即时通讯系统(IM)中,加密重要的通信消息,是一个常见的需求.尤其在一些政府部门的即时通信软件中(如税务系统),对即时聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据.我在最新 ...

  2. 二、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-腾讯云后台配置TXIM

    项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...

  3. 三、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-配置项目并实现IM登录

    项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...

  4. 国外青少年最喜爱的聊天 app,竟然是 Google Docs

    简评: 这还真不是标题党,Google Docs 的协作中内置了实时聊天的功能,也可以进行 comments,颇有种现代「传纸条」的既视感.其实国内的石墨文档.腾讯文档等协作工具也有类似的效果,本文很 ...

  5. 20 行代码极速为 App 加上聊天功能

    现在很多 App 都需要集成 IM 功能,今天就为大家分享一下集成 IM 基本功能的步骤.本文内容以 JMessage 为例.极光 IM ( JMessage ) = 极光推送 ( JPush ) + ...

  6. 用 JSQMessagesViewController 创建一个 iOS 聊天 App - 第 2 部分

    原文链接 : Create an iOS Chat App using JSQMessagesViewController – Part 2 原文作者 : Mariusz Wisniewski 译者 ...

  7. 七、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-聊天消息项的实现

    会话好友列表的实现 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展 ...

  8. Android 极光IM-高级篇-玩聊天app诞生

    距离上一次写 基础篇有了4个月,终于我写了一个 功能完善的即时通讯app,作为高级篇的担当出现.废话不多说,上图 app预览 ​​​​ ​​​​ ​​ 实现功能 1.用户的登录注册 2.单聊,能清空聊 ...

  9. 开发一款即时通讯App,从这几步开始

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 " ...

  10. APP Inventor 基于网络微服务器的即时通信APP

    APP Inventor 基于网络微服务器的即时通信APP 一.总结 一句话总结:(超低配版的QQ,逃~) 1.APP Inventor是什么? google 傻瓜式 编程 手机 app App In ...

随机推荐

  1. c语言实现基本的数据结构(六) 串

    #include <stdio.h> #include <tchar.h> #include <stdlib.h> // TODO: 在此处引用程序需要的其他头文件 ...

  2. DotNetCore 3.0 助力 WPF本地化

    概览 随着我们的应用程序越来越受欢迎,我们的下一步将要开发多语言功能.方便越来越多的国家使用我们中国的应用程序, 基于 WPF 本地化,我们很多时候使用的是系统资源文件,可是动态切换本地化,就比较麻烦 ...

  3. Apache性能测试工具ab使用详解~转载

    Apache自带性能测试工具ab使用详解 一. Apache的下载 1. http://www.apache.org/,进入Apache的官网 2. 将页面拖到最下方“Apache Project L ...

  4. luoguP2444_[POI2000]病毒

    题意 给定多个01模式串,问是否存在一个无限长的字符串不包含任何一个模式串. 分析 好像数据有点水,网上一大堆题解连样例都没过??? 多模式串,先把AC自动机建出来再说. 反向考虑,若存在一个无限长的 ...

  5. 运行MonkeyRunner时使用Genymotion模拟器

    Android自带的模拟器实在太慢太卡,远没有Genymotion的顺畅,所以找了一个办法,在启动py文件时使用Genymotion的模拟器 1.Genymotion安装完成之后,在Settings- ...

  6. SpringBoot:高并发下浏览量入库设计

    一.背景 文章浏览量统计,low的做法是:用户每次浏览,前端会发送一个GET请求获取一篇文章详情时,会把这篇文章的浏览量+1,存进数据库里. 1.1 这么做,有几个问题: 在GET请求的业务逻辑里进行 ...

  7. 常用Http status code 如何记

    一直记不住http常用的status code,最近思考可以这样想.http无非就是客户端和服务端之间请求嘛.结果么要么成功,要么失败. 成功了,可以提示信息 -- Informational 1xx ...

  8. input 上传图片

    <!--多图上传--><input name="image_mortgage_property[]" type="file" multiple ...

  9. 代码解读 | VINS 视觉前端

    本文作者是计算机视觉life公众号成员蔡量力,由于格式问题部分内容显示可能有问题,更好的阅读体验,请查看原文链接:代码解读 | VINS 视觉前端 vins前端概述 在搞清楚VINS前端之前,首先要搞 ...

  10. mysql count(*)与count(1)的区别

    count() 对行数进行计算,包括NULL: count(column) 计算特定的列的值的行数,不包括NULL: count(1)这个用法和count()的结果是一样的. http://blog. ...