ios uitextview 滚动复制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ios uitextview 滚动复制相关的知识,希望对你有一定的参考价值。
参考技术AUITextView是ios的富文本编辑控件,除了文字还可以插入图片等。今天主要介绍一下UITextView对自定义表情的处理。
1、首先识别出文本中的表情文本,然后在对应的位置插入NSTextAttachment对象,该对象存放的就是自定义表情。
1 static NSString *emojiTextPttern = @"\\\\[[0-9a-zA-Z\\\\u4e00-\\\\u9fa5]+\\\\]"; 2 3 _emojiDic = @@"[大笑]":@"smile",@"[爱心]":@"love"; 4 5 -(NSMutableAttributedString*)getEmojiText:(NSString*)content 6 NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:content attributes:self.typingAttributes]; 7 static NSRegularExpression *regExpress = nil; 8 if(regExpress == nil) 9 regExpress = [[NSRegularExpression alloc]initWithPattern:emojiTextPttern options:0 error:nil];10 11 //通过正则表达式识别出emojiText12 NSArray *matches = [regExpress matchesInString:content options:0 range:NSMakeRange(0, content.length)];13 if(matches.count > 0)14 for(NSTextCheckingResult *result in [matches reverseObjectEnumerator])15 NSString *emojiText = [content substringWithRange:result.range];16 //构造NSTextAttachment对象17 NSTextAttachment *attachment = [self createEmojiAttachment:emojiText];18 if(attachment)19 NSAttributedString *rep = [NSAttributedString attributedStringWithAttachment:attachment];20 //在对应的位置替换21 [attributedString replaceCharactersInRange:result.range withAttributedString:rep];22 23 24 25 return attributedString;26
2、构造NSTextAttachment的过程为:
1 -(NSTextAttachment*)createEmojiAttachment:(NSString*)emojiText 2 if(emojiText.length==0) 3 return nil; 4 5 NSString *imageName = _emojiDic[emojiText]; 6 if(imageName.length == 0) 7 return nil; 8 9 UIImage *image = [UIImage imageNamed:imageName];10 if(image == nil)11 return nil;12 13 //把图片缩放到符合当前textview行高的大小14 CGFloat emojiWHScale = image.size.width/1.0/image.size.height;15 CGSize emojiSize = CGSizeMake(self.font.lineHeight*emojiWHScale, self.font.lineHeight);16 UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, emojiSize.width, emojiSize.height)];17 imageView.image = image;18 //防止模糊19 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, [UIScreen mainScreen].scale);20 [imageView.layer renderInContext:UIGraphicsGetCurrentContext()];21 UIImage *emojiImage = UIGraphicsGetImageFromCurrentImageContext();22 UIGraphicsEndImageContext();23 EmojiTextAttachment *attachment = [[EmojiTextAttachment alloc]init];24 attachment.image = emojiImage;25 attachment.emojiText = emojiText;26 attachment.bounds = CGRectMake(0, -3, emojiImage.size.width, emojiImage.size.height);27 return attachment;28
其中EmojiTextAttachment继承了NSTextAttachment类,主要是为了记住自定义表情对应的emojiText,在后面实现copy和cut需要用到。EmojiTextAttachment声明为:
1 @interface EmojiTextAttachment : NSTextAttachment2 3 /**4 保存emojiText的值5 */6 @property (nonatomic, strong) NSString *emojiText;7 @end
3、实现对自定义表情的粘贴
重新paste方法即可
1 -(void)paste:(id)sender 2 UIPasteboard *defaultPasteboard = [UIPasteboard generalPasteboard]; 3 if(defaultPasteboard.string.length>0) 4 NSRange range = self.selectedRange; 5 if(range.location == NSNotFound) 6 range.location = self.text.length; 7 8 if([self.delegate textView:self shouldChangeTextInRange:range replacementText:defaultPasteboard.string]) 9 NSAttributedString *newAttriString = [self getEmojiText:defaultPasteboard.string];10 [self insertAttriStringToTextview:newAttriString];11 12 return;13 14 [super paste:sender];15 16 17 -(void)insertAttriStringToTextview:(NSAttributedString*)attriString18 NSMutableAttributedString *mulAttriString = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];19 NSRange range = self.selectedRange;20 if(range.location == NSNotFound)21 range.location = self.text.length;22 23 [mulAttriString insertAttributedString:attriString atIndex:range.location];24 self.attributedText = [mulAttriString copy];25 self.selectedRange = NSMakeRange(range.location+attriString.length, 0);26
4、实现自定义表情的拷贝和剪切
拷贝和剪切自定义表情的时候,不是获取自定义表情对应的图片而是自定义表情对应的emojiText,这也是我们在上面要定义EmojiTextAttachment类的原因。具体代码如下:
1 -(void)copy:(id)sender 2 NSRange range = self.selectedRange; 3 NSString *content = [self getStrContentInRange:range]; 4 if(content.length>0) 5 UIPasteboard *defaultPasteboard = [UIPasteboard generalPasteboard]; 6 [defaultPasteboard setString:content]; 7 return; 8 9 [super copy:sender];10 11 -(void)cut:(id)sender12 NSRange range = self.selectedRange;13 NSString *content = [self getStrContentInRange:range];14 if(content.length>0)15 [super cut:sender];16 UIPasteboard *defaultPasteboard = [UIPasteboard generalPasteboard];17 [defaultPasteboard setString:content];18 return;19 20 [super cut:sender];21 22 23 /**24 把textview的attributedText转化为NSString,其中把自定义表情转化为emojiText25 26 @param range 转化的范围27 @return 返回转化后的字符串28 */29 -(NSString*)getStrContentInRange:(NSRange)range30 NSMutableString *result = [[NSMutableString alloc]initWithCapacity:10];31 NSRange effectiveRange = NSMakeRange(range.location,0);32 NSUInteger length = NSMaxRange(range);33 while (NSMaxRange(effectiveRange)<length) 34 NSTextAttachment *attachment = [self.attributedText attribute:NSAttachmentAttributeName atIndex:NSMaxRange(effectiveRange) effectiveRange:&effectiveRange];35 if(attachment)36 if([attachment isKindOfClass:[EmojiTextAttachment class]])37 EmojiTextAttachment *emojiAttachment = (EmojiTextAttachment*)attachment;38 [result appendString:emojiAttachment.emojiText];39 40 41 else42 NSString *subStr = [self.text substringWithRange:effectiveRange];43 [result appendString:subStr];44 45 46 return [result copy];47
通过上面的努力,我们已经实现了所有的功能。但是我们用起来的时候,会发现两个问题:
1、在自定义表情的后面输入文本,UITextview设置的属性(比如字体大小,颜色等)都消失,又变成了默认属性;
2、在ios 10.11系统上,长按自定义表情的时候,keyboard会退出,并且弹出保存图片的系统窗口,这样的体验也不好。
解决第一个问题:
我们在初始化的时候保存一下UITextview的typingAttributes属性,然后在每次UITextview的内容将要发生变化的时候,重置一下他的该属性。
1 @interface ViewController ()<UITextViewDelegate> 2 @property (nonatomic, strong)CustomTextView *textView; 3 4 @property (nonatomic, strong)NSDictionary *typingAttributes; 5 @end 6 7 -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 8 textView.typingAttributes = self.typingAttributes; 9 return YES;10
解决第二个问题:
只需要实现一个delegate方法就行,直接返回NO
1 -(BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction2 return NO;3
swift iOS - Swift - UITextView滚动到底部扩展名
以上是关于ios uitextview 滚动复制的主要内容,如果未能解决你的问题,请参考以下文章
在 UITextView 上以编程方式禁用 iOS8 Quicktype 键盘