即時聊天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() {
        @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();
}
相關文章
相關標籤/搜索