環(huán)信提供了一個easeUI庫,其中實現(xiàn)了一些簡單的聊天界面。但是產品需求卻是要我們能夠在聊天界面中點擊圖片,并且可以查看大圖,在大圖頁面能夠左右滑動,類似qq以及微信的效果。
具體實現(xiàn)思路是,打開單人聊天界面時,開始從數(shù)據(jù)庫中加載消息,直到消息加載完成,然后從所有的消息中獲取屬于圖片的消息,然后保存到一個集合中,然后將這個集合中保存的圖片地址,通過viewpager展示出來。
思路理清之后,我們看一下相關的api:
一:EMConversation
這個類代表一個用戶的對話,從他這里可以獲取相關的消息。



上面這兩個方法,其中getAllMessages()代表回去內存中已經(jīng)加載的所有消息。loadMoreMsgFromDB()返回的是我們從本地數(shù)據(jù)庫中加載的消息。待會我們就是要從這里遍歷得到所有的圖片消息。
二:EaseChatFragment
EaseChatFragment他代表的就是當前我們打開的聊天頁面。我們主要是在這里對圖片信息進行篩選,保存。由于我們并不知道數(shù)據(jù)庫中到底有多少信息,因此我們需要不停調用EMConversation的loadMoreMsgFromDB()來獲取消息,直到我們讀取完畢。我們這里選用來handler來處理循環(huán)讀取。而handler處理循環(huán)讀取的觸發(fā)條件就是EMConversation初始化完成。
protected void onConversationInit() {
conversation = EMClient.getInstance().chatManager().getConversation(toChatUsername, EaseCommonUtils.getConversationType(chatType), true);
conversation.markAllMessagesAsRead();
// the number of messages loaded into conversation is getChatOptions().getNumberOfMessagesLoaded
// you can change this number
final List<EMMessage> msgs = conversation.getAllMessages();
int msgCount = msgs != null ? msgs.size() : 0;
if (msgCount < conversation.getAllMsgCount() && msgCount < pagesize) {
String msgId = null;
if (msgs != null && msgs.size() > 0) {
msgId = msgs.get(0).getMsgId();
}
conversation.loadMoreMsgFromDB(msgId, pagesize - msgCount);
}
handlerEM.sendEmptyMessage(111);
}

1:創(chuàng)建一個Runnable來處理我們讀到的消息。這個Runnable主要的思路是
(1):判斷當前是不是單一會話,如果是單一聊天,那么就先讀取內存中的所有消息,
(2):如果內存中的消息沒有20條的話,因為我們在一開始的時候就試圖從DB中加載20條消息,那就說明沒有更多消息了。
(3):如果內存中有20條消息,那么就繼續(xù)從DB中讀取,直到我們讀到的數(shù)據(jù)不夠20條為止。
(4):需要注意我們在調用loadMoreMsgFromDB()的時候,傳入的第一個參數(shù)是消息的id,我們應該取返回過來的集合當中的第一個消息的id,因為消息是從早到晚排列的,我們要想獲得更早的消息,就需要用第一個消息的id。
(5):環(huán)信有一個機制,就是當我們從DB中讀取消息的時候,讀出來的消息會保存到內存中。因此最終的消息,我們可以通過getAllMessages()來獲取。
//篩選出來的圖片信息
private ArrayList<String> imageuri;
//我們最終通過從內存中獲取所有消息。
private List<EMMessage> allMessages;
//臨時存放從消息db中取出的消息
private List<EMMessage> messagesEM;
//判斷是否有更多的消息了
private boolean isMoreEM=true;
//用來存放已經(jīng)取出的消息,根據(jù)他的大小來判斷有沒有更多的消息
ArrayList<EMMessage> emMessageArrayList =new ArrayList<>();
Runnable runnableeEM=new Runnable() {
@Override
public void run() {
try {
if (chatType == EaseConstant.CHATTYPE_SINGLE) {
if(emMessageArrayList.size()==0){
List<EMMessage> allMessages = conversation.getAllMessages();
messagesEM=conversation.loadMoreMsgFromDB(allMessages.get(0).getMsgId(),20);
emMessageArrayList.addAll(messagesEM);
}else{
messagesEM=conversation.loadMoreMsgFromDB(emMessageArrayList.get(0).getMsgId(),20);
emMessageArrayList.clear();
emMessageArrayList.addAll(messagesEM);
}
} else {
if(emMessageArrayList.size()==0){
List<EMMessage> allMessages = conversation.getAllMessages();
messagesEM=conversation.loadMoreMsgFromDB(allMessages.get(allMessages.size()-1).getMsgId(),20);
emMessageArrayList.addAll(messagesEM);
}else{
messagesEM=conversation.loadMoreMsgFromDB(emMessageArrayList.get(emMessageArrayList.size()-1).getMsgId(),20);
emMessageArrayList.clear();
emMessageArrayList.addAll(messagesEM);
}
}
} catch (Exception e1) {
return;
}
if (emMessageArrayList.size() > 0) {
if (emMessageArrayList.size() != 20) {
isMoreEM=false;
//沒有更多消息了
handlerEM.sendEmptyMessage(222);
Toast.makeText(getActivity(), getResources().getString(R.string.no_more_messages),
Toast.LENGTH_SHORT).show();
}else{
isMoreEM=true;
//還有更多消息
handlerEM.sendEmptyMessage(111);
}
} else {
isMoreEM=false;
//沒有更多消息了
handlerEM.sendEmptyMessage(222);
Toast.makeText(getActivity(), getResources().getString(R.string.no_more_messages),
Toast.LENGTH_SHORT).show();
}
}
};
2:創(chuàng)建一個handler來處理任務
(1):當發(fā)送的是111表示還有更多消息,于是就繼續(xù)從DB中獲取。
(2):當發(fā)送的是222表示沒有更多消息了,我們就可以獲取所有內存中的消息,然后遍歷取到圖片的消息。然后保存到集合中,當我們點擊圖片的時候使用。
Handler handlerEM = new Handler() {
@Override
public void handleMessage(android.os.Message message) {
switch (message.what){
case 111:
if(isMoreEM){
handlerEM.postDelayed(runnableeEM,1000);
}
break;
case 222:
allMessages = conversation.getAllMessages();
imageuri = new ArrayList<String>();
if(allMessages!=null){
for(EMMessage emMessage:allMessages){
if(emMessage.getBody() instanceof EMImageMessageBody) {
EMImageMessageBody imgBody = (EMImageMessageBody) emMessage.getBody();
imageuri.add(imgBody.getRemoteUrl());
}
}
}
break;
}
}
};
三:EaseChatRowImage
這個view代表的就是自定義的圖片view,他展示在聊天頁面中。在這個頁面我們的實現(xiàn)思路
(1):獲取到保存在imageuri中的圖片地址。
(2):傳遞到查看大圖的頁面中。
@Override
protected void onBubbleClick() {
Intent intent = new Intent(context, ViewBigImageActivity.class);
// File file = new File(imgBody.getLocalUrl());
Bundle bundle = new Bundle();
bundle.putInt("selet", 1);
// bundle.putInt("code", 0);
ArrayList<String> imageuri = easeChatFragment.getImageuri();
if(imageuri!=null&&imageuri.size()>0){
for(int i=0;i<imageuri.size();i++){
if(TextUtils.equals(imageuri.get(i),imgBody.getRemoteUrl())){
bundle.putInt("code", i);
}
}
}
// if (file.exists()) {
// bundle.putBoolean("isLocal", true);
// imageuri.add(imgBody.getLocalUrl());
// } else {
// imageuri.add(imgBody.getRemoteUrl());
// }
bundle.putStringArrayList("imageuri", imageuri);
if (message != null && message.direct() == EMMessage.Direct.RECEIVE && !message.isAcked()
&& message.getChatType() == EMMessage.ChatType.Chat) {
try {
EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());
} catch (Exception e) {
e.printStackTrace();
}
}
intent.putExtras(bundle);
context.startActivity(intent);
}
四:ViewBigImageActivity
查看大圖的頁面,其實就是一個Viewpager,和一個ImageLoader。如果要實現(xiàn)放大縮小的功能的話,可以使用開源庫uk.co.senab.photoview。這里就不再贅述了。