乐趣区

关于即时通讯:融云聊天页面长按消息后翻译功能的实现方法

我的项目要求实现“翻译”的性能,融云 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,对数据源中翻译好的内容进行展现。

代码局部

  1. 创立自定义 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

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

    import “RCDTextMessageCell.h”

    • (void)viewDidLoad {
      [super viewDidLoad];
      [self registerClass:[RCDTextMessageCell class] forMessageClass:[RCTextMessage class]];

    }

  3. 在聊天页面实现长按音讯的“翻译”办法:

    • 创立一个属性用于暂存长按时候的 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;

      }

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

    • 代码仅供参考,翻译的办法还须要本人来实现,把最终翻译好的后果赋值给 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];
      }
      }

    }

  5. 刷新 UI 时,显示翻译的内容,自定义 cell 会回调设置 CGSize 的办法,扭转 cell 高度,同时也会回调 setDataModel 办法,在这个办法中增加翻译的内容,具体能够参考自定义 cell 的 m 文件中代码,这里就不反复贴代码了。

到此为止,该性能曾经算是搞定了,同样这个思路和解决办法也实用于“语音转文字”,把翻译性能换成语音转文字,cell 继承于 RCVoiceMessageCell 就完了,心愿这篇分享能帮忙到大家。

退出移动版