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

聊天界面初始化时会得到一个参数,就是对方的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. 无重复字符的最长子串[双指针+哈希表] LeetCode.3

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  2. redis最基础的入门教程

      Redis最基础入门教程 简介 Redis 简介 Redis 优势 Redis与其他key-value存储有什么不同? 字符串(Strings) 哈希(Hash) 列表(List) 集合(Sets ...

  3. Spring入门(十):Spring AOP使用讲解

    1. 什么是AOP? AOP是Aspect Oriented Programming的缩写,意思是:面向切面编程,它是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 可以认为AOP是 ...

  4. Yarn上常驻Spark-Streaming程序调优

    对于长时间运行的Spark Streaming作业,一旦提交到YARN群集便需要永久运行,直到有意停止.任何中断都会引起严重的处理延迟,并可能导致数据丢失或重复.YARN和Apache Spark都不 ...

  5. spring security中@PreAuthorize注解的使用

    添加依赖<!-- oauth --><dependency> <groupId>org.springframework.cloud</groupId> ...

  6. C#ORM中的对象映射

    使用Linq.Expressions来动态生成映射方法 1.我们先写个简单的类Test,包含一个ID和Name. public class Test { public int? ID { get; s ...

  7. .NetCore从零开始使用Skywalking分布式追踪系统

    本文将从0开妈搭建两个webapi项目,使用Skywalking来追踪他们之间的调用关系及响应时间.开发环境为VisualStudio2019 1:安装Skywalking,可参考:https://w ...

  8. Ms Sql server 主键并发冲突解决办法

    问题原因,同事把表的自增长ID主键,改成是自定义的编号,没有严格的并发测试.在多线程同时插入数据时会引起主键冲突: 看了一些道友的文章,尝试了几个方法.经测试 使用 WITH(updlock)  可以 ...

  9. python 39 socketserver 模块并发通信

    socketserver模块 socketserver模块实现一个服务端与多个客户端通信.是在socket的基础上进行了一层封装,底层还是调用的socket. socketserver干了两件事: 1 ...

  10. HDU 1847

    题意略. 思路:又忘了dp,搜索这种暴力方法了.... #include<bits/stdc++.h> using namespace std; ; bool sg[maxn]; int ...