写点什么

融云聊天页面长按消息后“翻译”功能的实现方法

发布于: 2021 年 03 月 16 日

项目要求实现“翻译”的功能,融云 SDK 本身没这个功能,所以只能曲线救国了,通过自定义消息来实现,下面是功能实现相关内容。


资源链接:


官网:https://www.rongcloud.cn/自定义消息文档:https://docs.rongcloud.cn/v4/views/im/ui/guide/private/conversation/msgsend/ios.html#createcustom


实现思路


  1. 创建自定义 cell,与 SDK 内置的文本消息进行绑定。因为他们内置的文本消息 cell 不支持扩展显示翻译的内容,所以需要使用自定义 cell。

  2. 在聊天页面将自定义 cell 与内置的文本消息进行绑定。

  3. 重写长按消息 cell 的方法,判断如果是文本消息,增加“翻译”按钮。

  4. 点击“翻译”按钮,对文本内容进行翻译,并将翻译好的内容设置到数据源中。

  5. 刷新 UI,会触发自定义 cell 中的回调方法,在回调方法中重新设置高度,并添加 UI,对数据源中翻译好的内容进行展示。


代码部分


创建自定义 cell 继承于 RCTextMessageCell,m 文件中代码如下,具体效果可自行调整

#import "RCDTextMessageCell.h"
复制代码


复制代码


#define RCDScreenWidth [UIScreen mainScreen].bounds.size.width
复制代码


#define Font_Size 16
复制代码


#define Extra_BackgroupView_CornerRadius 6.f
复制代码


复制代码


@interface RCDTextMessageCell ()
复制代码


复制代码


//翻译内容的 Label
复制代码


@property (strong, nonatomic) UILabel *extraLabel;
复制代码


复制代码


//翻译内容的背景图
复制代码


@property (strong, nonatomic) UIView *extraBackgroundView;
复制代码


复制代码


@end
复制代码


复制代码


@implementation RCDTextMessageCell
复制代码


复制代码


+ (CGSize)sizeForMessageModel:(RCMessageModel *)model
复制代码


      withCollectionViewWidth:(CGFloat)collectionViewWidth
复制代码


         referenceExtraHeight:(CGFloat)extraHeight {
复制代码


    //翻译好的内容
复制代码


    NSString *extra = model.extra;
复制代码


    
复制代码


    CGSize superSize = [super sizeForMessageModel:model withCollectionViewWidth:collectionViewWidth referenceExtraHeight:extraHeight];
复制代码


    if (extra.length > 0) {
复制代码


        CGSize extraSize = [RCDTextMessageCell getTextLabelSize:extra];
复制代码


        CGFloat finalHeight = superSize.height + extraSize.height;
复制代码


        return CGSizeMake(superSize.width, finalHeight);
复制代码


    }else {
复制代码


        return superSize;
复制代码


    }
复制代码


}
复制代码


复制代码


//计算文本 size 的方法
复制代码


+ (CGSize)getTextLabelSize:(NSString *)content {
复制代码


    if ([content length] > 0) {
复制代码


        float maxWidth = RCDScreenWidth -
复制代码


        (10 + [RCIM sharedRCIM].globalMessagePortraitSize.width + 10) * 2 - 5 - 35;
复制代码


        CGRect textRect = [content
复制代码


                           boundingRectWithSize:CGSizeMake(maxWidth, 8000)
复制代码


                           options:(NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin |
复制代码


                                    NSStringDrawingUsesFontLeading)
复制代码


                           attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:Font_Size]}
复制代码


                           context:nil];
复制代码


        textRect.size.height = ceilf(textRect.size.height);
复制代码


        textRect.size.width = ceilf(textRect.size.width);
复制代码


        return CGSizeMake(textRect.size.width + 5, textRect.size.height + 5);
复制代码


    } else {
复制代码


        return CGSizeZero;
复制代码


    }
复制代码


}
复制代码


复制代码


- (void)setDataModel:(RCMessageModel *)model {
复制代码


    [super setDataModel:model];
复制代码


    NSString *extra = model.extra;
复制代码


    
复制代码


    //为了防止复用问题的处理
复制代码


    [self.extraLabel removeFromSuperview];
复制代码


    [self.extraBackgroundView removeFromSuperview];
复制代码


    
复制代码


    //如果有翻译的内容,添加 UI,进行展示
复制代码


    if (extra.length > 0) {
复制代码


        CGSize extraSize = [[self class] getTextLabelSize:extra];
复制代码


        CGRect superFrame = self.bubbleBackgroundView.frame;
复制代码


        CGRect extraBackgroundViewFrame = CGRectZero;
复制代码


        
复制代码


        //判断消息方向,设置翻译背景图的 frame
复制代码


        if (model.messageDirection == MessageDirection_SEND) {
复制代码


            extraBackgroundViewFrame = CGRectMake(superFrame.origin.x + superFrame.size.width - extraSize.width - 15, superFrame.size.height + 3, extraSize.width + 10, extraSize.height + 6);
复制代码


        } else {
复制代码


            extraBackgroundViewFrame = CGRectMake(superFrame.origin.x + 5, superFrame.origin.y + superFrame.size.height + 3, extraSize.width + 10, extraSize.height + 6);
复制代码


        }
复制代码


        
复制代码


        self.extraBackgroundView = [[UIView alloc] initWithFrame:extraBackgroundViewFrame];
复制代码


        self.extraBackgroundView.backgroundColor = [UIColor whiteColor];
复制代码


        self.extraBackgroundView.layer.cornerRadius = Extra_BackgroupView_CornerRadius;
复制代码


        [self.messageContentView addSubview:self.extraBackgroundView];
复制代码


        
复制代码


        CGRect extraLabelFrame = CGRectMake(8, 3, extraSize.width, extraSize.height);
复制代码


        self.extraLabel = [[UILabel alloc] initWithFrame:extraLabelFrame];
复制代码


        self.extraLabel.font = [UIFont systemFontOfSize:Font_Size];
复制代码


        self.extraLabel.numberOfLines = 0;
复制代码


        [self.extraLabel setLineBreakMode:NSLineBreakByWordWrapping];
复制代码


        [self.extraLabel setTextAlignment:NSTextAlignmentLeft];
复制代码


        [self.extraBackgroundView addSubview:self.extraLabel];
复制代码


        self.extraLabel.text = extra;
复制代码


    }
复制代码


}
复制代码


复制代码


@end
复制代码

在聊天页面类导入并绑定自定义 cell :

#import "RCDTextMessageCell.h"
复制代码


复制代码


- (void)viewDidLoad {
复制代码


    [super viewDidLoad];    
复制代码


    [self registerClass:[RCDTextMessageCell class] forMessageClass:[RCTextMessage class]];
复制代码


}
复制代码

在聊天页面实现长按消息的“翻译”方法:

  • 创建一个属性用于暂存长按时候的 model。

@property (strong, nonatomic) RCMessageModel *longTouchModel;
复制代码

重写长按消息 cell 的方法,判断如果是文本消息,增加“翻译”按钮,translate 是实现“翻译”的方法。

- (NSArray<UIMenuItem *> *)getLongTouchMessageCellMenuList:(RCMessageModel *)model {
复制代码


    NSMutableArray<UIMenuItem *> *menuList = [[super getLongTouchMessageCellMenuList:model] mutableCopy];
复制代码


    if ([model.content isKindOfClass:[RCTextMessage class]]) {
复制代码


        UIMenuItem *forwardItem = [[UIMenuItem alloc] initWithTitle:@"翻译"
复制代码


                                                             action:@selector(translate)];
复制代码


        self.longTouchModel = model;
复制代码


        [menuList addObject:forwardItem];
复制代码


    }
复制代码


    return menuList;
复制代码


}
复制代码

实现“翻译”方法,并将翻译好的内容设置到数据源中:

  • 代码仅供参考,翻译的方法还需要自己来实现,把最终翻译好的结果赋值给 self.longTouchModel.extra

  • 这里必须要提的是 cellSize = CGSizeZero,否则刷新 UI 不会改变 cell 的高度

  • 刷新 self.conversationMessageCollectionView

  • 如果翻译的是最后一条消息,需要滚动到底部,否则翻译的内容会被遮挡

- (void)translate {
复制代码


    if (self.longTouchModel) {
复制代码


        NSString *result = @"翻译后的结果。";
复制代码


        RCTextMessage *txtMsg = (RCTextMessage *)self.longTouchModel.content;
复制代码


        if ([txtMsg.content isEqualToString:@"How are you?"]) {
复制代码


            result = @"你好吗?";
复制代码


        } else if ([txtMsg.content isEqualToString:@"I’m fine."]) {
复制代码


            result = @"我很好。";
复制代码


        }
复制代码


        self.longTouchModel.extra = result;
复制代码


        self.longTouchModel.cellSize = CGSizeZero;
复制代码


        [self.conversationMessageCollectionView reloadData];
复制代码


        RCMessageModel *model = [self.conversationDataRepository lastObject];
复制代码


        if (model.messageId == self.longTouchModel.messageId ) {
复制代码


            [self scrollToBottomAnimated:YES];
复制代码


        }
复制代码


    }
复制代码


}
复制代码

刷新 UI 时,显示翻译的内容,自定义 cell 会回调设置 CGSize 的方法,改变 cell 高度,同时也会回调 setDataModel 方法,在这个方法中添加翻译的内容,具体可以参考自定义 cell 的 m 文件中代码,这里就不重复贴代码了。


到此为止,该功能已经算是搞定了,同样这个思路和处理方法也适用于“语音转文字”,把翻译功能换成语音转文字,cell 继承于 RCVoiceMessageCell 就完了,希望这篇分享能帮助到大家。


用户头像

还未添加个人签名 2021.01.26 加入

还未添加个人简介

评论

发布
暂无评论
融云聊天页面长按消息后“翻译”功能的实现方法