即时聊天APP(五) - 聊天界面
设置界面没什么好说的,无非也就是加了个对话框来二次提醒用户,现在来讲讲聊天界面。
聊天界面初始化时会得到一个参数,就是对方的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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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+"......");elselis = new ConList(friend,"对方:"+show+"......");
}else {if(msg.getType() == 1)lis = new ConList(friend,"我:"+msg.getContent());elselis = new ConList(friend,"对方:"+msg.getContent());
}
lis.save();
}
转载于:https://www.cnblogs.com/zqm-sau/p/10331959.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
