• 李洪强iOS开发之-环信05_EaseUI 使用指南


    李洪强iOS开发之-环信05_EaseUI 使用指南

    EaseUI 使用指南


    EaseUI 封装了 IM 功能常用的控件(如聊天会话、会话列表、联系人列表)。旨在帮助开发者快速集成环信 SDK。

    源码地址:

    第 1 步:集成 EaseUI 前,首先需要集成环信 iOS SDK,参考:集成文档

    第 2 步:参考ChatDemo3.0 导入的方式,直接将EaseUI拖入已经集成SDK的项目中

    第 1 步:引入相关头文件 #import “EaseUI.h”。

    第 2 步:在工程的 AppDelegate 中的以下方法中,调用 EaseUI 对应方法。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[EaseSDKHelper shareHelper] easemobApplication:application
                        didFinishLaunchingWithOptions:launchOptions
                                               appkey:@"douser#istore"
                                         apnsCertName:@"istore_dev"
                                          otherConfig:@{kSDKConfigEnableConsoleLogger:[NSNumber numberWithBool:YES]}];
        return YES;
    }

    创建聊天会话、传递用户或群 ID 和会话类型(EMConversationType)。

    EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:@"8001" conversationType:EMConversationTypeChat];

    EaseUI 提供现成的聊天会话 ViewController,可以通过继承 EaseMessageViewController 方式(参考 ChatDemo-UI3.0 中 ChatViewController)实现对聊天会话的扩展。

    也可以直接使用 EaseMessageViewController,通过 EaseMessageViewControllerDelegate 和 EaseMessageViewControllerDataSource 两个协议实现对 EaseMessageViewController 的扩展。

    实现自定义聊天样式

    EaseMessageViewControllerDelegate

    获取自定义消息 cell,根据 messageModel,用户自己判断是否显示自定义消息 cell。如果返回 nil 会显示默认;如果返回 cell 会显示用户自定义消息cell。

    /*!
     @method
     @brief 获取消息自定义cell
     @discussion 用户根据messageModel判断是否显示自定义cell。返回nil显示默认cell,否则显示用户自定义cell
     @param tableView 当前消息视图的tableView
     @param messageModel 消息模型
     @result 返回用户自定义cell
     */
    - (UITableViewCell *)messageViewController:(UITableView *)tableView
                           cellForMessageModel:(id<IMessageModel>)messageModel;
     
    /*!
     @method
     @brief 获取消息cell高度
     @discussion 用户根据messageModel判断,是否自定义显示cell的高度
     @param viewController 当前消息视图
     @param messageModel 消息模型
     @param cellWidth 视图宽度
     @result 返回用户自定义cell
     */
    - (CGFloat)messageViewController:(EaseMessageViewController *)viewController
               heightForMessageModel:(id<IMessageModel>)messageModel
                       withCellWidth:(CGFloat)cellWidth;
     
    //具体创建自定义Cell的样例:
    - (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id<IMessageModel>)model
    {
        //样例为如果消息是文本消息显示用户自定义cell
        if (model.bodyType == eMessageBodyType_Text) {
            NSString *CellIdentifier = [CustomMessageCell cellIdentifierWithModel:model];
            //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell
            CustomMessageCell *cell = (CustomMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (cell == nil) {
                cell = [[CustomMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];
                cell.selectionStyle = UITableViewCellSelectionStyleNone;
            }
            cell.model = model;
            return cell;
        }
        return nil;
    }
     
    - (CGFloat)messageViewController:(EaseMessageViewController *)viewController
               heightForMessageModel:(id<IMessageModel>)messageModel
                       withCellWidth:(CGFloat)cellWidth
    {
        //样例为如果消息是文本消息使用用户自定义cell的高度
        if (messageModel.bodyType == EMMessageBodyTypeText) {
            //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell
            return [CustomMessageCell cellHeightWithModel:messageModel];
        }
        return 0.f;
    }

    通过自定义cell展示动态表情的效果图:

    选中消息的回调

    /*!
     @method
     @brief 选中消息的回调
     @discussion 用户根据messageModel判断,是否自定义处理消息选中时间。返回YES为自定义处理,返回NO为默认处理
     @param viewController 当前消息视图
     @param messageModel 消息模型
     @result 是否采用自定义处理
     */
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
            didSelectMessageModel:(id<IMessageModel>)messageModel;
     
    //选中消息回调的样例:
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
            didSelectMessageModel:(id<IMessageModel>)messageModel
    {
        BOOL flag = NO;
        //样例为如果消息是文件消息用户自定义处理选中逻辑
        switch (messageModel.bodyType) {
            case EMMessageBodyTypeImage:
            case EMMessageBodyTypeLocation:
            case EMMessageBodyTypeVideo:
            case EMMessageBodyTypeVoice:
                break;
            case EMMessageBodyTypeFile:
            {
                flag = YES;
                NSLog(@"用户自定义实现");
            }
                break;
            default:
                break;
        }
        return flag;
    }

    用户选中头像的回调

    /*!
     @method
     @brief 点击消息头像
     @discussion 获取用户点击头像回调
     @param viewController 当前消息视图
     @param messageModel 消息模型
     @result
     */
    - (void)messageViewController:(EaseMessageViewController *)viewController
        didSelectAvatarMessageModel:(id<IMessageModel>)messageModel;
     
    //获取用户点击头像回调的样例:
    - (void)messageViewController:(EaseMessageViewController *)viewController
       didSelectAvatarMessageModel:(id<IMessageModel>)messageModel
    {
        //UserProfileViewController用户自定义的个人信息视图
        //样例的逻辑是选中消息头像后,进入该消息发送者的个人信息
        UserProfileViewController *userprofile = [[UserProfileViewController alloc] initWithUsername:messageModel.message.from];
        [self.navigationController pushViewController:userprofile animated:YES];
    }

    录音按钮状态的回调

    /*!
     @method
     @brief 底部录音功能按钮状态回调
     @discussion 获取底部录音功能按钮状态回调,根据EaseRecordViewType,用户自定义处理UI的逻辑
     @param viewController 当前消息视图
     @param recordView 录音视图
     @param type 录音按钮当前状态
     @result
     */
    - (void)messageViewController:(EaseMessageViewController *)viewController
                  didSelectRecordView:(UIView *)recordView
                    withEvenType:(EaseRecordViewType)type;
     
    //录音按钮状态的回调样例:
    - (void)messageViewController:(EaseMessageViewController *)viewController
              didSelectRecordView:(UIView *)recordView
                     withEvenType:(EaseRecordViewType)type
    {
        /*
            EaseRecordViewTypeTouchDown,//录音按钮按下
            EaseRecordViewTypeTouchUpInside,//手指在录音按钮内部时离开
            EaseRecordViewTypeTouchUpOutside,//手指在录音按钮外部时离开
            EaseRecordViewTypeDragInside,//手指移动到录音按钮内部
            EaseRecordViewTypeDragOutside,//手指移动到录音按钮外部
        */
        //根据type类型,用户自定义处理UI的逻辑
        switch (type) {
            case EaseRecordViewTypeTouchDown:
            {
                if ([self.recordView isKindOfClass:[EaseRecordView class]]) {
                    [(EaseRecordView *)self.recordView  recordButtonTouchDown];
                }
            }
                break;
            case EaseRecordViewTypeTouchUpInside:
            {
                if ([self.recordView isKindOfClass:[EaseRecordView class]]) {
                    [(EaseRecordView *)self.recordView recordButtonTouchUpInside];
                }
                [self.recordView removeFromSuperview];
            }
                break;
            case EaseRecordViewTypeTouchUpOutside:
            {
                if ([self.recordView isKindOfClass:[EaseRecordView class]]) {
                    [(EaseRecordView *)self.recordView recordButtonTouchUpOutside];
                }
                [self.recordView removeFromSuperview];
            }
                break;
            case EaseRecordViewTypeDragInside:
            {
                if ([self.recordView isKindOfClass:[EaseRecordView class]]) {
                    [(EaseRecordView *)self.recordView recordButtonDragInside];
                }
            }
                break;
            case EaseRecordViewTypeDragOutside:
            {
                if ([self.recordView isKindOfClass:[EaseRecordView class]]) {
                    [(EaseRecordView *)self.recordView recordButtonDragOutside];
                }
            }
                break;
            default:
                break;
        }
    }

    EaseMessageViewControllerDataSource

    用户判断消息是否允许长按,返回布尔值;如果用户允许长按,此方法为通知用户触发长按手势,返回布尔值,如果返回 NO 默认方式处理,返回 YES 采用用户自定义的处理方式。

    /*!
     @method
     @brief 是否允许长按
     @discussion 获取是否允许长按的回调,默认是NO
     @param viewController 当前消息视图
     @param indexPath 长按消息对应的indexPath
     @result
     */
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
       canLongPressRowAtIndexPath:(NSIndexPath *)indexPath;
     
    /*!
     @method
     @brief 触发长按手势
     @discussion 获取触发长按手势的回调,默认是NO
     @param viewController 当前消息视图
     @param indexPath 长按消息对应的indexPath
     @result
     */
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
       didLongPressRowAtIndexPath:(NSIndexPath *)indexPath;
     
    //长按收拾回调样例:
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
       canLongPressRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //样例给出的逻辑是所有cell都允许长按
        return YES;
    }
     
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
       didLongPressRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //样例给出的逻辑是长按cell之后显示menu视图
        id object = [self.dataArray objectAtIndex:indexPath.row];
        if (![object isKindOfClass:[NSString class]]) {
            EaseMessageCell *cell = (EaseMessageCell *)[self.tableView cellForRowAtIndexPath:indexPath];
            [cell becomeFirstResponder];
            self.menuIndexPath = indexPath;
            [self _showMenuViewController:cell.bubbleView andIndexPath:indexPath messageType:cell.model.bodyType];
        }
        return YES;
    }

    Demo3.0实现的消息长按效果演示:

    将EMMessage类型转换为符合<IMessageModel>协议的类型,设置用户信息,消息显示用户昵称和头像。

    /*!
     @method
     @brief 将EMMessage类型转换为符合<IMessageModel>协议的类型
     @discussion 将EMMessage类型转换为符合<IMessageModel>协议的类型,设置用户信息,消息显示用户昵称和头像
     @param viewController 当前消息视图
     @param EMMessage 聊天消息对象类型
     @result 返回<IMessageModel>协议的类型
     */
    - (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                               modelForMessage:(EMMessage *)message;
     
    //具体样例:
    - (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                               modelForMessage:(EMMessage *)message
    {
        //用户可以根据自己的用户体系,根据message设置用户昵称和头像
        id<IMessageModel> model = nil;
        model = [[EaseMessageModel alloc] initWithMessage:message];
        model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像
        model.avatarURLPath = @"";//头像网络地址
        model.nickname = @"昵称";//用户昵称
        return model;
    }

    聊天会话页面头像和昵称的效果演示:

    聊天会话样式自定义

    聊天样式的自定义需要在 EaseMessageViewController 中 viewDidload 结束前设置。

    //@property中带有UI_APPEARANCE_SELECTOR,都可以通过set的形式设置样式,具体可以参考EaseBaseMessageCell.h,EaseMessageCell.h
     
    [[EaseBaseMessageCell appearance] setSendBubbleBackgroundImage:[[UIImage imageNamed:@"chat_sender_bg"] stretchableImageWithLeftCapWidth:5 topCapHeight:35]];//设置发送气泡
    [[EaseBaseMessageCell appearance] setRecvBubbleBackgroundImage:[[UIImage imageNamed:@"chat_receiver_bg"] stretchableImageWithLeftCapWidth:35 topCapHeight:35]];//设置接收气泡
     
    [[EaseBaseMessageCell appearance] setAvatarSize:40.f];//设置头像大小
    [[EaseBaseMessageCell appearance] setAvatarCornerRadius:20.f];//设置头像圆角

    EaseSDKHelper 封装了发送消息的方法。

    具体发送消息样例:

    /*
     EMChatTypeChat            单聊消息
     EMChatTypeGroupChat       群聊消息
     EMChatTypeChatRoom        聊天室消息
    */
     
    //发送文字消息
    EMMessage *message = [EaseSDKHelper sendTextMessage:@"要发送的消息"
                                                     to:@"6001"//接收方
                                            messageType:EMChatTypeChat//消息类型
                                             messageExt:nil]; //扩展信息                                          
    //发送位置消息
    EMMessage *message = [EaseSDKHelper sendLocationMessageWithLatitude:35.1//经度
                                                              longitude:35.1//纬度
                                                                address:"地址"
                                                                     to:@"6001"//接收方
                                                            messageType:EMChatTypeChat//消息类型
                                                             messageExt:nil];//扩展信息                                         
     
    //发送图片消息      
    EMMessage *message = [EaseSDKHelper sendImageMessageWithImageData:imageData//发送的图片数据NSData
                                                                   to:@"6001"//接收方
                                                          messageType:EMChatTypeChat//消息类型
                                                           messageExt:nil];//扩展信息                                                    
     
    //发送音频消息                                           
    EMMessage *message = [EaseSDKHelper sendVoiceMessageWithLocalPath:localPath//音频本地地址
                                                             duration:duration//语音的时长,单位是秒
                                                                   to:@"6001"//接收方
                                                          messageType:EMChatTypeChat//消息类型
                                                           messageExt:nil];//扩展信息
     
    //发送视频文件消息
    EMMessage *message = [EaseSDKHelper sendVideoMessageWithURL:url//发送的视频地址
                                                             to:@"6001"//接收方
                                                    messageType:EMChatTypeChat//消息类型
                                                     messageExt:nil];//扩展信息
     
    //发送构造成功的消息                                                   
    [[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {
     
    }];                                                                                                                                                                                                                                                   
     
    EaseConversationListViewController *chatListVC = [[EaseConversationListViewController alloc] init];

    EaseConversationListViewControllerDataSource

    用户根据 conversationModel 实现,实现自定义会话中最后一条消息文案的显示内容。

    /*!
     @method
     @brief 获取最后一条消息显示的内容
     @discussion 用户根据conversationModel实现,实现自定义会话中最后一条消息文案的显示内容
     @param conversationListViewController 当前会话列表视图
     @param IConversationModel 会话模型
     @result 返回用户最后一条消息显示的内容
     */
    - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
          latestMessageTitleForConversationModel:(id<IConversationModel>)conversationModel;
     
     
    /*!
     @method
     @brief 获取最后一条消息显示的时间
     @discussion 用户可以根据conversationModel,自定义实现会话列表中时间文案的显示内容
     @param conversationListViewController 当前会话列表视图
     @param IConversationModel 会话模型
     @result 返回用户最后一条消息时间的显示文案
     */
    - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
           latestMessageTimeForConversationModel:(id<IConversationModel>)conversationModel;
     
    //最后一条消息展示内容样例    
    - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
          latestMessageTitleForConversationModel:(id<IConversationModel>)conversationModel
    {
        NSString *latestMessageTitle = @"";
        EMMessage *lastMessage = [conversationModel.conversation latestMessage];
        if (lastMessage) {
            EMMessageBody *messageBody = lastMessage.body;
            switch (messageBody.type) {
                case EMMessageBodyTypeImage:{
                    latestMessageTitle = NSLocalizedString(@"message.image1", @"[image]");
                } break;
                case EMMessageBodyTypeText:{
                    // 表情映射。
                    NSString *didReceiveText = [EaseConvertToCommonEmoticonsHelper
                                                convertToSystemEmoticons:((EMTextMessageBody *)messageBody).text];
                    latestMessageTitle = didReceiveText;
                    if ([lastMessage.ext objectForKey:MESSAGE_ATTR_IS_BIG_EXPRESSION]) {
                        latestMessageTitle = @"[动画表情]";
                    }
                } break;
                case EMMessageBodyTypeVoice:{
                    latestMessageTitle = NSLocalizedString(@"message.voice1", @"[voice]");
                } break;
                case EMMessageBodyTypeLocation: {
                    latestMessageTitle = NSLocalizedString(@"message.location1", @"[location]");
                } break;
                case EMMessageBodyTypeVideo: {
                    latestMessageTitle = NSLocalizedString(@"message.video1", @"[video]");
                } break;
                case EMMessageBodyTypeFile: {
                    latestMessageTitle = NSLocalizedString(@"message.file1", @"[file]");
                } break;
                default: {
                } break;
            }
        }
     
        return latestMessageTitle;
    }
     
    //最后一条消息展示时间样例  
    - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
           latestMessageTimeForConversationModel:(id<IConversationModel>)conversationModel
    {
        NSString *latestMessageTime = @"";
        EMMessage *lastMessage = [conversationModel.conversation latestMessage];;
        if (lastMessage) {
            latestMessageTime = [NSDate formattedTimeFromTimeInterval:lastMessage.timestamp];
        }
        return latestMessageTime;
    }

    会话列表最后一条消息和时间显示的效果演示:

    EaseConversationListViewControllerDelegate

    点击会话列表用户可以根据 conversationModel 自定义处理逻辑。

    /*!
     @method
     @brief 获取点击会话列表的回调
     @discussion 获取点击会话列表的回调后,点击会话列表用户可以根据conversationModel自定义处理逻辑
     @param conversationListViewController 当前会话列表视图
     @param IConversationModel 会话模型
     @result
     */
    - (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
                didSelectConversationModel:(id<IConversationModel>)conversationModel;
     
    //会话列表点击的回调样例
    - (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
                didSelectConversationModel:(id<IConversationModel>)conversationModel
    {
        //样例展示为根据conversationModel,进入不同的会话ViewController
            if (conversationModel) {
            EMConversation *conversation = conversationModel.conversation;
            if (conversation) {
                if ([[RobotManager sharedInstance] isRobotWithUsername:conversation.conversationId]) {
                    RobotChatViewController *chatController = [[RobotChatViewController alloc] initWithConversationChatter:conversation.conversationId conversationType:conversation.type];
                    chatController.title = [[RobotManager sharedInstance] getRobotNickWithUsername:conversation.conversationId];
                    [self.navigationController pushViewController:chatController animated:YES];
                } else {
                    ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:conversation.conversationId conversationType:conversation.type];
                    chatController.title = conversationModel.title;
                    [self.navigationController pushViewController:chatController animated:YES];
                }
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:@"setupUnreadMessageCount" object:nil];
            [self.tableView reloadData];
        }
    }
     

    联系人列表初始化

    EaseUsersListViewController *listViewController = [[EaseUsersListViewController alloc] init];

    联系人列表扩展

    需要实现 EMUserListViewControllerDataSource。

    根据 buddy 获取用户自定信息,联系人列表里展示昵称和头像。

    /*!
     @method
     @brief 获取用户模型
     @discussion 根据buddy获取用户自定信息,联系人列表里展示昵称和头像
     @param userListViewController 当前联系人视图
     @param buddy 好友的信息描述类
     @result 返回用户模型
     */
    - (id<IUserModel>)userListViewController:(EaseUsersListViewController *)userListViewController
                               modelForBuddy:(NSString *)buddy;
     
    //联系人列表扩展样例
    - (id<IUserModel>)userListViewController:(EaseUsersListViewController *)userListViewController
                               modelForBuddy:(NSString *)buddy
    {
        //用户可以根据自己的用户体系,根据buddy设置用户昵称和头像
        id<IUserModel> model = nil;
        model = [[EaseUserModel alloc] initWithBuddy:buddy];
        model.avatarURLPath = @"";//头像网络地址
        model.nickname = @"昵称";//用户昵称
        return model;
    }

    联系人列表头像和昵称的效果演示:

  • 相关阅读:
    给DOM元素绑定click事件也有学问
    几个JavaScript的浏览器差异处理问题
    CSS样式权重的级联cascade的概念
    你知道HTML标签设计的本意吗?
    一些奇怪的JavaScript试题
    JavaScript如何计算两个日期间的时间差
    Vim默认开启语法标识功能
    理解Python中的继承规则和继承顺序
    An Easy Introduction to CUDA C and C++
    super()
  • 原文地址:https://www.cnblogs.com/LiLihongqiang/p/5753332.html
Copyright © 2020-2023  润新知