UILabel&UITextView文本嵌入图片处理
发布日期:2022-03-18 08:27:41 浏览次数:38 分类:技术文章

本文共 7559 字,大约阅读时间需要 25 分钟。

NSTextAttachment objects are used by the NSAttributedString class cluster as the values for attachment attributes (stored in the attributed string under the key named NSAttachmentAttributeName).

UILabel

下面通过例子,给UILabel的文字后面跟上一个emoji:

//创建NSTextAttachment    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];    attachment.image = [UIImage imageNamed:@"emoji"];    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"后面跟着图片"];    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 6)];    [attributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, 6)];    NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];    [attributedString insertAttributedString:attachmentString atIndex:6];    //设置attributedText    _label.attributedText = attributedString;

效果如下:

这里写图片描述

上图的例子中,emoji图片偏大,位置也偏上,如何调整?参考。

可以通过调整bounds来解决:

NSTextAttachment *attachment = [[NSTextAttachment alloc] init];    attachment.image = [UIImage imageNamed:@"emoji"];    attachment.bounds = CGRectMake(0, -5, 20, 20);

调整之后的效果如下:

这里写图片描述

也可以继承NSTextAttachment,然后重写- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex方法:

@interface MYNSAttachment : NSTextAttachment@end@implementation MYNSAttachment- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex{    return CGRectMake( 0 , -5 , lineFrag.size.height , lineFrag.size.height);}@end

这里写图片描述

请参考:

UITextView

转载自

前言

在iOS开发中,经常需要用UITextView作为编辑文本的输入控件。

但是如何在编辑时插入自定义表情呢?就是像发微博时那样?

本文简单的用NSTextAttachment、NSAttributedString的特性,实现了

  • 在UITextView中编辑文字时插入自定义表情图片
  • 同时可以返回带有表情“替换符”的纯文本字符串。

示例

本文代码工程地址:

效果图:

这里写图片描述

背景知识

  • NSAttributedString及其子类,用于显示富文本。
  • NSTextAttachment,NSAttributedString的一种样式类,可以在文本中显示图片。
  • NSTextStorage,UITextView中的实际的文本封装。(见参考中的UITextView文档)

表情与其标志

首先需要明确的是,我们的自定义表情一定是有一一对应的“标志”的,如“[/emoji_haha]”。

就是说,为了方便处理,方便在数据库、网络传输中保存、传输带有表情图片的文本,我们必须要为每种表情取特定的“名字”,数据库中储存的、网络传输的文本就只包含这些标志名字就行,在显示的时候做对应的替换。

如:

tutuge.me
这里写图片描述

对应的纯文本就是:

tutuge.me[/emoji_1]

插入并显示表情图片

插入表情很简单,直接实例化NSTextAttachment类,将需要的表情的UIImage实例赋值给NSTextAttachment的image属性,然后用“[NSAttributedString attributedStringWithAttachment:]”方法实例化一个NSAttributedString的对象,插入到UITextView的textStorage对应的位置即可。

如下:

NSTextAttachment *emojiTextAttachment = [NSTextAttachment new];//设置表情图片emojiTextAttachment.image = emojiImage;//插入表情[textView.textStorage insertAttributedString:[NSAttributedString attributedStringWithAttachment:emojiTextAttachment]                                      atIndex:textView.selectedRange.location];

这样,就能在UITextView当前光标位置插入表情图片了。

获取带有表情标志的文本字符串

难点

NSTextAttachment被插入到NSAttributedString中的时候,就被当成了一个字符处理!!!。

就是说,只从UITextView的text中,是找不回文本里面不同的表情所对应的标志的!

解决点

  1. 我们要能遍历出当前文本中所有的表情,也就是NSTextAttachment类。
  2. 我们要能知道遍历出的表情,对应的标志是什么。

遍历所有的NSTextAttachment类属性

遍历,嗯,先看看Apple有没有提供相应的方法,能遍历NSAttributedString(及其子类)的属性的。查阅文档:NSAttributedString Class Reference,可以找到这么一个方法:“- enumerateAttribute:inRange:options:usingBlock:”,其原型如下:

- (void)enumerateAttribute:(NSString *)attrName                   inRange:(NSRange)enumerationRange                   options:(NSAttributedStringEnumerationOptions)opts                usingBlock:(void (^)(id value,                                     NSRange range,                                     BOOL *stop))block

用处:

Executes the Block for the specified attribute run in the specified range.

看,就是这个方法~就能遍历出NSTextAttachment对象了~

创建NSTextAttachment的子类

如何绑定NSTextAttachment所表示的表情和与其对应的标志?创建子类嘛~直接在子类中增加属性,保存标志不就行了。

如下:

@interface EmojiTextAttachment : NSTextAttachment@property(strong, nonatomic) NSString *emojiTag;@end

所以,这个时候,插入表情的代码应该就是下面这样:

EmojiTextAttachment *emojiTextAttachment = [EmojiTextAttachment new];//保存表情标志emojiTextAttachment.emojiTag = emojiTag;//设置表情图片emojiTextAttachment.image = emojiImage;//插入表情[textView.textStorage insertAttributedString:[NSAttributedString attributedStringWithAttachment:emojiTextAttachment]                                      atIndex:textView.selectedRange.location];

创建NSAttributedString的Category

最后,就是将这个遍历表情、拼接最终文本字符串的方法设置成NSAttributedString的自定义Category方法,以方便直接调用。

当然,这里面有些细节的处理,如替换表情标志时的字符串偏移量计算等,看代码吧。

如下:

//NSAttributedString+EmojiExtension.h@interface NSAttributedString (EmojiExtension)- (NSString *)getPlainString;@end//NSAttributedString+EmojiExtension.m@implementation NSAttributedString (EmojiExtension)- (NSString *)getPlainString {    //最终纯文本    NSMutableString *plainString = [NSMutableString stringWithString:self.string];    //替换下标的偏移量    __block NSUInteger base = 0;    //遍历    [self enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, self.length)                     options:0                  usingBlock:^(id value, NSRange range, BOOL *stop) {                      //检查类型是否是自定义NSTextAttachment类                      if (value && [value isKindOfClass:[EmojiTextAttachment class]]) {                          //替换                          [plainString replaceCharactersInRange:NSMakeRange(range.location + base, range.length)                                                     withString:((EmojiTextAttachment *) value).emojiTag];                       //增加偏移量                                                    base += ((EmojiTextAttachment *) value).emojiTag.length - 1;                      }                  }];    return plainString;}@end

使用

直接调用getPlainString方法即可。

总结

其实本文也是来源于最近的项目需求,在网上一直找不到比较好的解决方案,就自己摸索出来一个。至于复杂的图文混合编辑,当然还是Core Text来的强大(自己也在学习中)~

如果有更好地办法,一定要告诉我啊~~~

参考

转载自

前言

本文是基于写的,主要实现了在UITextView插入表情图片时,自定义表情大小的功能。

Github

本文代码工程地址:

Gif示例图

这里写图片描述

关键点

首先要明确我们要什么,很简单,就是指定NSTextAttachment在被绘制时的大小。

所以,按照这个思路,就可以去找找NSTextAttachment类的相关方法,看能不能通过继承或其他的方式改变大小。

幸运的是,NSTextAttachment实现了“NSTextAttachmentContainer”这个Protocol,而这个Protocol里面有如下方法:

- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer                      proposedLineFragment:(CGRect)lineFrag                             glyphPosition:(CGPoint)position                            characterIndex:(NSUInteger)charIndex

再看看其解释:

Returns the layout bounds of the text attachment to the layout manager. (required)

也就是说,在绘制NSTextAttachment的内容的时候,内容的“Bounds”是通过这个方法获得的。所以,可以重写这个方法,来达到我们的目的。

继续扩展NSTextAttachment类

保存自定义Size

根据之前的定义,我们在自定义的类“EmojiTextAttachment”中再加一个保存大小的属性,如下:

//EmojiTextAttachment类定义@interface EmojiTextAttachment : NSTextAttachment//表情的字符串表示,见前文@property(strong, nonatomic) NSString *emojiTag;//新增:保存当前表情图片的大小@property(assign, nonatomic) CGFloat emojiSize;@end

有了“emojiSize”这个属性,我们就可以在自由的指定每个NSTextAttachment的大小。

重写

接下来就是重写方法,不多说,见代码:

//EmojiTextAttachment实现@implementation EmojiTextAttachment//重点!重写NSTextAttachmentContainer Protocol的方法- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {    //根据emojiSize计算新的大小    return [self scaleImageSizeToWidth:_emojiSize];}//计算新的图片大小//这里不涉及对图片实际数据的压缩,所以不用异步处理~- (CGRect)scaleImageSizeToWidth:(CGFloat)width {    //缩放系数    CGFloat factor = 1.0;    //获取原本图片大小    CGSize oriSize = [self.image size];    //计算缩放系数    factor = (CGFloat) (width / oriSize.width);    //创建新的Size    CGRect newSize = CGRectMake(0, 0, oriSize.width * factor, oriSize.height * factor);    return newSize;}@end

使用

增加了emojiSize属性后,我们就可以在创建表情,甚至创建后,自由的调整每个NSTextAttachment的大小。

总结

一共只增加了十几行代码,但是效果还是不错哒~

转载地址:https://windzen.blog.csdn.net/article/details/53609918 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:iOS自定义控件二
下一篇:NSAttributedString

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年03月05日 12时52分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

kubelet配置cni插件_浅谈 Kubernetes 网络模型(CNI) 2019-04-21
exception日志 php_关于PHP中如何开启debug讲解 2019-04-21
我的世界超能物质纳米机器人_武汉理工大学在微纳米马达研究方面取得突破性进展... 2019-04-21
antv g6对接后台数据_看时下流行的数据可视化大屏设计工具 2019-04-21
删除的vue怎么找回_新版微信功能!微信删除好友怎么找回?快速恢复,真的不难... 2019-04-21
什么叫pin脚的pad_“傻子”是什么意思? 2019-04-21
电子合同的履行_信达教育 |《民法典》新规来了,明确电子合同签订履行规则... 2019-04-21
从左上角到右下角 棋盘问题_科目二考试详解,有时间多看看,考试一次过不是问题... 2019-04-21
相等变为1 编号_电气控制柜怎样看线号接线?电气线路接线编号方法 2019-04-21
系列有什么区别_华为的Mate和P系列有什么区别?绝不止拍照这么简单! 2019-04-21
线程池原理_直击线程池底层原理 2019-04-21
平均值_Echarts图表配置显示最大、最小及平均值 2019-04-21
文件传输_FTP文件传输协议详解 2019-04-21
自带的jvm监控不准_Java性能调优:JVM性能监控常用方法 2019-04-21
cad引出线段lisp_利用lisp给CAD直线取整? 2019-04-21
北师大版图形的旋转二教案_2018北师大版四年级上册教案:《图形的旋转》(2)... 2019-04-21
mysql隐式事务_MySQL系列-第14篇:事务详解 2019-04-21
mysql成批删除c语言_C语言操作mysql 添加、删除、修改、查询实例 2019-04-21
mysql57服务和mysql_本地计算机上的MySQL57服务已启动,然后停止 2019-04-21
mysql远程端口_MySql的远程访问和远程端口开放方法 2019-04-21