环信提供了一个easeUI库,其中实现了一些简单的聊天界面。但是产品需求却是要我们能够在聊天界面中点击图片,并且可以查看大图,在大图页面能够左右滑动,类似qq以及微信的效果。
具体实现思路是,打开单人聊天界面时,开始从数据库中加载消息,直到消息加载完成,然后从所有的消息中获取属于图片的消息,然后保存到一个集合中,然后将这个集合中保存的图片地址,通过viewpager展示出来。
思路理清之后,我们看一下相关的api:
一:EMConversation
这个类代表一个用户的对话,从他这里可以获取相关的消息。
上面这两个方法,其中getAllMessages()代表回去内存中已经加载的所有消息。loadMoreMsgFromDB()返回的是我们从本地数据库中加载的消息。待会我们就是要从这里遍历得到所有的图片消息。
二:EaseChatFragment
EaseChatFragment他代表的就是当前我们打开的聊天页面。我们主要是在这里对图片信息进行筛选,保存。由于我们并不知道数据库中到底有多少信息,因此我们需要不停调用EMConversation的loadMoreMsgFromDB()来获取消息,直到我们读取完毕。我们这里选用来handler来处理循环读取。而handler处理循环读取的触发条件就是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:创建一个Runnable来处理我们读到的消息。这个Runnable主要的思路是
(1):判断当前是不是单一会话,如果是单一聊天,那么就先读取内存中的所有消息,
(2):如果内存中的消息没有20条的话,因为我们在一开始的时候就试图从DB中加载20条消息,那就说明没有更多消息了。
(3):如果内存中有20条消息,那么就继续从DB中读取,直到我们读到的数据不够20条为止。
(4):需要注意我们在调用loadMoreMsgFromDB()的时候,传入的第一个参数是消息的id,我们应该取返回过来的集合当中的第一个消息的id,因为消息是从早到晚排列的,我们要想获得更早的消息,就需要用第一个消息的id。
(5):环信有一个机制,就是当我们从DB中读取消息的时候,读出来的消息会保存到内存中。因此最终的消息,我们可以通过getAllMessages()来获取。
//筛选出来的图片信息
private ArrayList<String> imageuri;
//我们最终通过从内存中获取所有消息。
private List<EMMessage> allMessages;
//临时存放从消息db中取出的消息
private List<EMMessage> messagesEM;
//判断是否有更多的消息了
private boolean isMoreEM=true;
//用来存放已经取出的消息,根据他的大小来判断有没有更多的消息
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:创建一个handler来处理任务
(1):当发送的是111表示还有更多消息,于是就继续从DB中获取。
(2):当发送的是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,他展示在聊天页面中。在这个页面我们的实现思路
(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。如果要实现放大缩小的功能的话,可以使用开源库uk.co.senab.photoview。这里就不再赘述了。