
本文共 9841 字,大约阅读时间需要 32 分钟。
开源中国的”弹一弹”中处理emoji的过程
emoji键盘
开源中国的emoji键盘类为EmojiPageVC
,继承自UIPageViewController
,为分页控制器。分页控制器的每个页面上的控制器类型为EmojiPanelVC
,继承自UIViewController
。
EmojiPanelVC
使用UICollectionView
来布局emoji。EmojiPanelVC
还有两个block回调: void (^didSelectEmoji)(NSTextAttachment *textAttachment)
:表示的是点击某个emoji后的回调void (^deleteEmoji)()
:表示的是删除某个emoji的回调
UICollectionView
的数据源是一个名为emoji.plist
的plist文件,只使用了其中的一部分。plist转为字典,key对应的的为名称字符串,value对应的为image的名称。如下:
点击UICollectionView
的某一项之后的调用的结果如下:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ NSInteger section = indexPath.section; NSInteger row = indexPath.row; if (section == 2 && row == 6) { //block回调,删除 _deleteEmoji(); } else { NSInteger emojiNum = _pageIndex * 20 + section * 7 + row + 1; NSString *emojiImageName, *emojiStr; if (emojiNum >= 106) { //emojiNum大于等于106的图片,图片名称类似为":finnadie:" emojiStr = Utils.emojiDict[@(emojiNum).stringValue]; //去掉":" emojiImageName = [emojiStr stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; } else { //emojiNum小于106的图片,图片名称类似为"084" emojiStr = [NSString stringWithFormat:@"[%ld]", emojiNum - 1]; emojiImageName = [NSString stringWithFormat:@"%03ld", emojiNum]; } //创建Attachment NSTextAttachment *textAttachment = [NSTextAttachment new]; textAttachment.image = [UIImage imageNamed:emojiImageName]; [textAttachment adjustY:-3];//调整位置 //给textAttachment关联一个对象 objc_setAssociatedObject(textAttachment, @"emoji", emojiStr, OBJC_ASSOCIATION_RETAIN_NONATOMIC); //block回调,参数为NSTextAttachment _didSelectEmoji(textAttachment); }}
在EmojiPageVC
中处理回调。例如我们输入”we”后,再输入一个emoji。处理的过程如下:
_didSelectEmoji = ^(NSTextAttachment *textAttachment) { //选择了一个emoji //通过NSTextAttachment创建emoji属性字符串 NSAttributedString *emojiAttributedString = [NSAttributedString attributedStringWithAttachment:textAttachment]; //通过textView的attributedText创建一个新的mutableAttributeString NSMutableAttributedString *mutableAttributeString = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText]; //使用emojiAttributedString来替换 [mutableAttributeString replaceCharactersInRange:textView.selectedRange withAttributedString:emojiAttributedString]; //赋值给textView的attributedText textView.attributedText = mutableAttributeString; textView.textColor = [UIColor titleColor]; [textView insertText:@""]; textView.font = [UIFont systemFontOfSize:16]; };
删除emoji:
_deleteEmoji = ^ {//删除一个emoji [textView deleteBackward]; };
上传emoji
发表一个”弹一弹”,在上传过程中如何处理emoji?
开源中国是这样处理的:+ (NSString *)convertRichTextToRawText:(UITextView *)textView{ NSMutableString *rawText = [[NSMutableString alloc] initWithString:textView.text]; //遍历其中的attachment [textView.attributedText enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, textView.attributedText.length) options:NSAttributedStringEnumerationReverse usingBlock:^(NSTextAttachment *attachment, NSRange range, BOOL *stop) { if (!attachment) { return;} //存在attachment,获取关联对象,即emojiStr,可能为[x]或者":xxxx:" NSString *emojiStr = objc_getAssociatedObject(attachment, @"emoji"); //出入字符串 [rawText insertString:emojiStr atIndex:range.location]; }]; //匹配iOS系统的emoji NSString *pattern = @"[\ue000-\uf8ff]|[\\x{1f300}-\\x{1f7ff}]|\\x{263A}\\x{FE0F}|☺"; NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; NSArray *resultsArray = [re matchesInString:textView.text options:0 range:NSMakeRange(0, textView.text.length)]; //emoji转为text的字典 NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"emojiToText" ofType:@"plist"]; NSDictionary *emojiToText = [[NSDictionary alloc] initWithContentsOfFile:path]; //把iOS系统的emoji替换为文字,例如":grinning::sweat_smile:" for (NSTextCheckingResult *match in [resultsArray reverseObjectEnumerator]) { NSString *emoji = [textView.text substringWithRange:match.range]; [rawText replaceCharactersInRange:match.range withString:emojiToText[emoji]]; } return [rawText stringByReplacingOccurrencesOfString:@"\U0000fffc" withString:@""];}
举个例子说明,我们输入以下的内容:
最看是rawText的内容为:
textView.attributedText遍历其中的NSAttachmentAttributeName之后,rawText的内容为:
需要注意的是,在emoji.plist文件中是这样定义的:
然后是替换,系统的emoji,之后rawText内容为:
网络获取emoji之后的显示
发表”弹一弹”之后,在cell中显示动弹。网络获取的内容为:
aa:grinning::sweat_smile:[色][色]
这时需要把字符串替换为emoji
+ (NSAttributedString *)emojiStringFromRawString:(NSString *)rawString{ //创建属性字符处 NSMutableAttributedString *emojiString = [[NSMutableAttributedString alloc] initWithString:rawString]; //emoji字典 NSDictionary *emoji = self.emojiDict; //匹配emoji unicode编码[\u4e00-\u9fa5]匹配所有中文 NSString *pattern = @"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]|:[a-zA-Z0-9\\u4e00-\\u9fa5_]+:"; NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; NSArray *resultsArray = [re matchesInString:rawString options:0 range:NSMakeRange(0, rawString.length)]; NSMutableArray *emojiArray = [NSMutableArray arrayWithCapacity:resultsArray.count]; for (NSTextCheckingResult *match in resultsArray) { NSRange range = [match range]; NSString *emojiName = [rawString substringWithRange:range]; if ([emojiName hasPrefix:@"["] && emoji[emojiName]) { //自定义的emoji,带"["的 //创建attachment 添加图片 NSTextAttachment *textAttachment = [NSTextAttachment new]; textAttachment.image = [UIImage imageNamed:emoji[emojiName]]; //调整位置 [textAttachment adjustY:-3]; //创建attribute string NSAttributedString *emojiAttributedString = [NSAttributedString attributedStringWithAttachment:textAttachment]; //创建字典,,添加到emojiArray中 [emojiArray addObject: @{@"image": emojiAttributedString, @"range": [NSValue valueWithRange:range]}]; } else if ([emojiName hasPrefix:@":"]) { //以":"开头的 if (emoji[emojiName]) { //emoji字典中存在的 [emojiArray addObject:@{@"text": emoji[emojiName], @"range": [NSValue valueWithRange:range]}]; } else { //emoji字典中不存在的 UIImage *emojiImage = [UIImage imageNamed:[emojiName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]]; NSTextAttachment *textAttachment = [NSTextAttachment new]; textAttachment.image = emojiImage; [textAttachment adjustY:-3]; NSAttributedString *emojiAttributedString = [NSAttributedString attributedStringWithAttachment:textAttachment]; [emojiArray addObject: @{@"image": emojiAttributedString, @"range": [NSValue valueWithRange:range]}]; } } } //遍历emojiArray for (NSInteger i = emojiArray.count -1; i >= 0; i--) { NSRange range; [emojiArray[i][@"range"] getValue:&range];//获取range //替换range中的内容 if (emojiArray[i][@"image"]) { [emojiString replaceCharactersInRange:range withAttributedString:emojiArray[i][@"image"]]; } else { [emojiString replaceCharactersInRange:range withString:emojiArray[i][@"text"]]; } } return emojiString;}
处理后的结果为:
Coding iOS客户端”发冒泡”处理emoji过程
emoji键盘
Coding的emoji键盘使用的是AGEmojiKeyboardView
类,由改变而来。支持普通的emoji,也支持大图Monkey和Monkey_Gif(自定义的)。如下:
点击一个emoji之后,调用的代理方法- (void)emojiKeyBoardView:(AGEmojiKeyboardView *)emojiKeyBoardView didUseEmoji:(NSString *)emoji
:
- (void)emojiKeyBoardView:(AGEmojiKeyboardView *)emojiKeyBoardView didUseEmoji:(NSString *)emoji { NSRange selectedRange = self.tweetContentView.selectedRange; NSString *emotion_monkey = [emoji emotionMonkeyName]; if (emotion_monkey) { //monkey类emoji表情 emotion_monkey = [NSString stringWithFormat:@" :%@: ", emotion_monkey]; self.tweetContentView.text = [self.tweetContentView.text stringByReplacingCharactersInRange:selectedRange withString:emotion_monkey]; self.tweetContentView.selectedRange = NSMakeRange(selectedRange.location +emotion_monkey.length, 0); [self textViewDidChange:self.tweetContentView]; }else{ //非monkey类emoji表情 self.tweetContentView.text = [self.tweetContentView.text stringByReplacingCharactersInRange:selectedRange withString:emoji]; self.tweetContentView.selectedRange = NSMakeRange(selectedRange.location +emoji.length, 0); [self textViewDidChange:self.tweetContentView]; }}
输入如下的emoji,,之后,textView的文本内容是:
上传emoji
上传emoji的时候,需要把emoji转为字符。Coding使用的是开源项目,在其基础上加了一些内容。转后的结果为:
:smiley: :哈哈: :奔月:
基本逻辑是遍历字符串,然后替换字符串:
[text enumerateSubstringsInRange:NSMakeRange(0, text.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { if (self.aliaseForEmojis[substring]) { NSString *aliase = self.aliaseForEmojis[substring]; resultText = [resultText stringByReplacingOccurrencesOfString:substring withString:aliase]; } }];
把字符串转为emoji
貌似的是Coding在后台给处理了。如下
转载地址:https://windzen.blog.csdn.net/article/details/53609943 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关于作者
