从零到一撸个YYLabel

从零到一撸个YYLabel,第1张

在学习YYText过程中,分析完YYLabel原理后一时手痒,自己撸了个JKRichLabel,写文记录,也算功德圆满。相较于YYLabel,JKRichLabel更适合初学者通过阅读源码学习技术,毕竟大神的东西不好懂,有精力的童鞋强烈建议阅读YYLabel源码(虽然JKRichLabel更好懂,但是功力离YY大神差太远)

为保证界面流畅,各种技术层出不穷。JKRichLabel继承自UIView,基本复原了UILabel的功能特性,在此基础上采用压缩图层,异步绘制,可以更好的解决卡顿问题,并且内部通过core text绘制,支持图文混排。

JKRichLabel还很脆弱,欢迎感兴趣的童鞋一起完善ta

以JKRichLabel为载体,JKAsyncLayer为核心,在JKRichLabelLayout中通过core text进行绘制。JKRichLabelLine是CTLine的拓展,包含一行要绘制的信息。JKTextInfo包含属性文本的基本信息,类似于CTRun。JKTextInfoContainer是JKTextInfo的容器,并且JKTextInfoContainer可以合并JKTextInfoContainer。同时,JKTextInfoContainer负责判断是否可以响应用户交互

JKAsyncLayer相较于YYTextAsyncLayer对部分逻辑进行调整,其余逻辑基本相同。JKAsyncLayer是整个流程中异步绘制的核心。

JKAsyncLayer继承自CALayer,UIView内部持有CALayer,JKRichLabel继承自UIView。因此,只要将JKRichLabel内部的layer替换成JKAsyncLayer就可以完成异步绘制。

JKAsyncLayer绘制核心思想:在异步线程中获取context上下文,绘制背景色,生成image context,跳回主线程将image赋值给layer.contents。异步线程确保界面的流畅性,生成图片后赋值给contents可以压缩图层,同样能够提高界面的流畅性

JKRichLabel内部含有text与attributedText属性,分别支持普通文本与属性文本,不管是哪种文本,内部都转成属性文本_innerText,并通过_innerText进行绘制

JKRichLabelLayout是绘制具体内容的核心,通过core text可以完成attachment的绘制

可见,绘制图文混排必然要将attachment添加到CFAttributedStringRef中,然而并没有接口可以将attachment转换成字符串

JKRichLabel的lineBreakMode暂不支持 NSLineBreakByTruncatingHead 和 NSLineBreakByTruncatingMiddle ,如果赋值为这两种属性,会自动转换为 NSLineBreakByTruncatingTail

效果图中有Long Text的例子,label外套scrollview,将scrollview的contentSize设置为label的size,label的size通过sizeToFit自动计算。如果文字足够长,这种方案就over了

Demo

YYLabel实现方式

//1.简单显示label

YYLabel *label = [YYLabel new]

label.frame = CGRectMake(100,50,100,25)

label.font = [UIFont systemFontOfSize:14.0f]

label.textColor = [UIColororangeColor]

label.textAlignment=NSTextAlignmentCenter

label.lineBreakMode=0

label.numberOfLines = NSLineBreakByWordWrapping

label.text=@"YYTextDemo Test"

//    [self.view addSubview:label]

//2.属性字符串 简单实用

NSMutableAttributedString*text= [[NSMutableAttributedStringalloc] initWithString:@"上海市第九城市信息技术有限公司"]

text.font = [UIFontboldSystemFontOfSize:13.0f]

text.color = [UIColorblueColor]

[textsetColor:[UIColor redColor]range:NSMakeRange(0,4)]

//    给你的label添加点击事件

[textsetTextHighlightRange:NSMakeRange(0,4)

color:[UIColor orangeColor]

backgroundColor:[UIColorwhiteColor]

tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){

NSLog(@"tap text range:...")

}]

YYLabel *attributedLabel = [YYLabel new]

attributedLabel.frame = CGRectMake(100,100,160,25)

attributedLabel.attributedText = text

attributedLabel.userInteractionEnabled=YES

attributedLabel.backgroundColor = [UIColor purpleColor]

//    [self.view addSubview:attributedLabel]

//3.图文混排模式

NSMutableAttributedString *textImage = [NSMutableAttributedString new]

UIFont *font= [UIFont systemFontOfSize:14.0f]

inti =2

switch(i) {

case0:

{

//    方式一

NSString*title =@"2006年的诺贝尔文学奖颁给了土耳其作家奥尔罕.帕慕克。在很多人都很意外的时候,我心头却感到一阵开心,因为早在两年前,我就知道了这个作家"

[textImageappendAttributedString:[[NSAttributedString alloc] initWithString:title attributes:nil]]

UIImage *image = [UIImage imageNamed:@"babilogo"]

image= [UIImage imageWithCGImage:image.CGImage scale:5orientation:UIImageOrientationUp]

NSMutableAttributedString*attachText= [NSMutableAttributedStringattachmentStringWithContent:image contentMode:UIViewContentModeCenter attachmentSize:image.size alignToFont:font alignment:YYTextVerticalAlignmentCenter]

[textImage appendAttributedString:attachText]

[textImageappendAttributedString:[[NSAttributedString alloc] initWithString:@"凭借《我的名字叫红》获得了都柏林文学..."attributes:nil]]

break

}

case1:

{

NSString *title=@"text 与 UIView混排:"

[textImageappendAttributedString:[[NSAttributedStringalloc] initWithString:title attributes:nil]]

UISwitch *switcher = [UISwitch new]

switcher.frame= CGRectMake(0,0,50,50)

[switcher sizeToFit]

NSMutableAttributedString*attachText = [NSMutableAttributedString attachmentStringWithContent:switcher contentMode:UIViewContentModeCenter attachmentSize:switcher.frame.size alignToFont:font alignment:YYTextVerticalAlignmentCenter]

[textImageappendAttributedString:attachText]

[textImageappendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"attributes:nil]]

break

}

case2:

{

NSString*title =@"2006年的诺贝尔文学奖颁给了土耳其作家奥尔罕.帕慕克。在很多人都很意外的时候,我心头却感到一阵开心,因为早在两年前,我就知道了这个作家"

[textImage appendAttributedString:[[NSAttributedString alloc] initWithString:title attributes:nil]]

UIImageView *imageView = [UIImageView new]

imageView.frame= CGRectMake(0,0,20,20)

[imageViewsetImage:[UIImage imageNamed:@"babilogo"]]

imageView.contentMode =UIViewContentModeScaleAspectFill

imageView.userInteractionEnabled=YES

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithActionBlock:^(id_Nonnullsender) {

NSLog(@"ImageAction")

}]

[imageViewaddGestureRecognizer:tap]

NSMutableAttributedString*attachText = [NSMutableAttributedStringattachmentStringWithContent:imageView contentMode:UIViewContentModeCenter attachmentSize:imageView.frame.size alignToFont:font alignment:YYTextVerticalAlignmentCenter]

[textImageappendAttributedString:attachText]

NSString*subTitle=@"凭借《我的名字叫红》获得了都柏林文学,2006年的诺贝尔文学奖颁给了土耳其作家奥尔罕.帕慕克。在很多人都很意外的时候,我心头却感到一阵开心,因为早在两年前,我就知道了这个作家"

[textImageappendAttributedString:[[NSAttributedString alloc] initWithString:subTitle attributes:nil]]

NSMutableParagraphStyle*paragraphStyle= [[NSMutableParagraphStylealloc] init]

[paragraphStylesetLineSpacing:16]//调整行间距

[textImage addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [title length]+[subTitle length])]

[textImage setTextHighlightRange:NSMakeRange(0,8)

color:[UIColor orangeColor]

backgroundColor:[UIColor whiteColor]

tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){

NSLog(@"tap text range:...")

}]

break

}

default:

break

}

textImage.font = font

YYLabel *textImageLabel = [YYLabel new]

textImageLabel.userInteractionEnabled =YES

textImageLabel.numberOfLines =0

textImageLabel.frame = CGRectMake(0,0,320,400)

textImageLabel.attributedText = textImage

//    [self.view addSubview:textImageLabel]

基本实现思路就是利用正则识别链接加YYLabel设置链接点击事件,下面说下这过程中遇到的问题

1、自动布局YYLabel后发现设置label.numberOfLines = 0后不换行,YYLabel还得设置一个preferredMaxLayoutWidth属性,这个属性是设置最大宽度,设置完才能有换行功能

2、添加YYLabel的分类并且利用正则识别链接

3、通过给NSAttributedString设置高亮并且添加点击事件

4、添加完点击事件后点击发现并没有响应,是因为label的父类试图添加了点击手势导致的手势冲突解决办法是给父试图的手势添加代理并且实现代理方法


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/bake/11289213.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存