项目要求实现“翻译”的功能,融云 SDK 本身没这个功能,所以只能曲线救国了,通过自定义消息来实现,下面是功能实现相关内容。
资源链接:
官网:https://www.rongcloud.cn/ 自定义消息文档:https://docs.rongcloud.cn/v4/views/im/ui/guide/private/conversation/msgsend/ios.html#createcustom
实现思路
- 创建自定义 cell,与 SDK 内置的文本消息进行绑定。因为他们内置的文本消息 cell 不支持扩展显示翻译的内容,所以需要使用自定义 cell。
- 在聊天页面将自定义 cell 与内置的文本消息进行绑定。
- 重写长按消息 cell 的方法,判断如果是文本消息,增加“翻译”按钮。
- 点击“翻译”按钮,对文本内容进行翻译,并将翻译好的内容设置到数据源中。
- 刷新 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- (CGSize)sizeForMessageModel:(RCMessageModel *)model
在聊天页面类导入并绑定自定义 cell :
import "RCDTextMessageCell.h"
- (void)viewDidLoad {
[super viewDidLoad];
[self registerClass:[RCDTextMessageCell class] forMessageClass:[RCTextMessage class]];
}
- (void)viewDidLoad {
在聊天页面实现长按消息的“翻译”方法:
- 创建一个属性用于暂存长按时候的 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;
}
- (NSArray<UIMenuItem *> )getLongTouchMessageCellMenuList:(RCMessageModel )model {
实现“翻译”方法,并将翻译好的内容设置到数据源中:
- 代码仅供参考,翻译的方法还需要自己来实现,把最终翻译好的结果赋值给 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 就完了,希望这篇分享能帮助到大家。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。