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

本文共 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

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年03月22日 14时15分25秒

关于作者

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

推荐文章

matlab wash矩阵产生,洗衣机净衣效能与衣损程度的关系分析 2021-06-24
php中如何调用sql server,php调用SQL SERVER 2008及以上版本的方法 2021-06-24
python多线程实现kmeans,3种方式实现python多线程并发处理 2021-06-24
matlab 变量不存在,matlab程序运行时提示变量未定义 2021-06-24
php编码函数 base58,1. Base58可逆加密 2021-06-24
oracle 在需要下列之一,Oracle存储过程中PLS-00103:出现符号“/”在需要下列之一时:(... 2021-06-24
oracle10g dblink优化,Oracle10g通过dblink访问数据异常 2021-06-24
linux安装时的iso文件,直接用ISO文件在linux上安装新系统 2021-06-24
linux修改文件权限为所有人都可以访问,Linux 笔记分享八:文件权限的设定 2021-06-24
linux中卸载ambri-servle,Kerberos 命令使用 2021-06-24
linux二进制反编译,Xori:一款来自BlackHat 2018的二进制反汇编和静态分析工具 2021-06-24
linux两台主机添加信任,Linux两台机器间添加信任,实现不用密码问,互传文件... 2021-06-24
linux 自动获取ssl证书,linux生成自验证ssl证书的具体命令和步骤 2021-06-24
linux基础命令20个,20-linux中基础命令 2021-06-24
重置网络配置 android,重置Android移动网络信号? 2021-06-24
java约瑟夫环pta上_cdoj525-猴子选大王 (约瑟夫环) 2021-06-24
java++记录+运行_记录java+testng运行selenium(三)---xml、ini、excel、日志等配置 2021-06-24
mysql居左查询abcd_MySql速查手册 2021-06-24
loadrunner 错误: 无法找到 java.exe_LoadRunner错误及解决方法总结 2021-06-24
Java小魔女芭芭拉_沉迷蘑菇不可自拔,黏土人《小魔女学园》苏西·曼芭芭拉 图赏... 2021-06-24