CA*Layer(CAShapeLayer--CATextLayer)
CAShapeLayer
CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图 形,最后CAShapeLayer就自动渲染出来了。当然,你也可以用Core Graphics直接向原始的CALyer的内容中绘制一个路径,相比直下,使用CAShapeLayer有以下一些优点:
渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉(如我们在第二章所见)。
不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。
#import "DrawingView.h"#import @interface ViewController ()@property (nonatomic, weak) IBOutlet UIView *containerView;@end@implementation ViewController- (void)viewDidLoad{ [super viewDidLoad]; //create path UIBezierPath *path = [[UIBezierPath alloc] init]; [path moveToPoint:CGPointMake(175, 100)]; ? [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES]; [path moveToPoint:CGPointMake(150, 125)]; [path addLineToPoint:CGPointMake(150, 175)]; [path addLineToPoint:CGPointMake(125, 225)]; [path moveToPoint:CGPointMake(150, 175)]; [path addLineToPoint:CGPointMake(175, 225)]; [path moveToPoint:CGPointMake(100, 150)]; [path addLineToPoint:CGPointMake(200, 150)]; //create shape layer CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.strokeColor = [UIColor redColor].CGColor; shapeLayer.fillColor = [UIColor clearColor].CGColor; shapeLayer.lineWidth = 5; shapeLayer.lineJoin = kCALineJoinRound; shapeLayer.lineCap = kCALineCapRound; shapeLayer.path = path.CGPath; //add it to our view [self.containerView.layer addSublayer:shapeLayer];}@end
//define path parametersCGRect rect = CGRectMake(50, 50, 100, 100);CGSize radii = CGSizeMake(20, 20);UIRectCorner corners = UIRectCornerTopRight | UIRectCornerBottomRight | UIRectCornerBottomLeft;//create pathUIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];@interface ViewController ()@property (nonatomic, weak) IBOutlet UIView *labelView;@end@implementation ViewController- (void)viewDidLoad{ [super viewDidLoad]; //create a text layer CATextLayer *textLayer = [CATextLayer layer]; textLayer.frame = self.labelView.bounds; [self.labelView.layer addSublayer:textLayer]; //set text attributes textLayer.foregroundColor = [UIColor blackColor].CGColor; textLayer.alignmentMode = kCAAlignmentJustified; textLayer.wrapped = YES; //choose a font UIFont *font = [UIFont systemFontOfSize:15]; //set layer font CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFontRef fontRef = CGFontCreateWithFontName(fontName); textLayer.font = fontRef; textLayer.fontSize = font.pointSize; CGFontRelease(fontRef); //choose some text NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis"; //set layer text textLayer.string = text;}@end textLayer.contentsScale = [UIScreen mainScreen].scale;这样就解决了这个问题(如图6.3)

@implementation ViewController- (void)viewDidLoad{ [super viewDidLoad]; //create a text layer CATextLayer *textLayer = [CATextLayer layer]; textLayer.frame = self.labelView.bounds; textLayer.contentsScale = [UIScreen mainScreen].scale; [self.labelView.layer addSublayer:textLayer]; //set text attributes textLayer.alignmentMode = kCAAlignmentJustified; textLayer.wrapped = YES; //choose a font UIFont *font = [UIFont systemFontOfSize:15]; //choose some text NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc \ elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis"; ? //create attributed string NSMutableAttributedString *string = nil; string = [[NSMutableAttributedString alloc] initWithString:text]; //convert UIFont to a CTFont CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFloat fontSize = font.pointSize; CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL); //set text attributes NSDictionary *attribs = @{ (__bridge id)kCTForegroundColorAttributeName:(__bridge id)[UIColor blackColor].CGColor, (__bridge id)kCTFontAttributeName: (__bridge id)fontRef }; [string setAttributes:attribs range:NSMakeRange(0, [text length])]; attribs = @{ (__bridge id)kCTForegroundColorAttributeName: (__bridge id)[UIColor redColor].CGColor, (__bridge id)kCTUnderlineStyleAttributeName: @(kCTUnderlineStyleSingle), (__bridge id)kCTFontAttributeName: (__bridge id)fontRef }; [string setAttributes:attribs range:NSMakeRange(6, 5)]; //release the CTFont we created earlier CFRelease(fontRef); //set layer text textLayer.string = string;}@end
我们已经证实了CATextLayer比UILabel有着更好的性能表现,同时还有额外的布局选项并且在iOS 5上支持富文本。但是与一般的标签比较而言会更加繁琐一些。如果我们真的在需求一个UILabel的可用替代品,最好是能够在Interface Builder上创建我们的标签,而且尽可能地像一般的视图一样正常工作。
我们应该继承UILabel,然后添加一个子图层 CATextLayer并重写显示文本的方法。但是仍然会有由UILabel的-drawRect:方法创建的空寄宿图。而且由于CALayer不支持自 动缩放和自动布局,子视图并不是主动跟踪视图边界的大小,所以每次视图大小被更改,我们不得不手动更新子图层的边界。
我们真正想要的是一个用CATextLayer作为宿主图层的UILabel子类,这样就可以随着视图自动调整大小而且也没有冗余的寄宿图啦。
就 像我们在第一章『图层树』讨论的一样,每一个UIView都是寄宿在一个CALayer的示例上。这个图层是由视图自动创建和管理的,那我们可以用别的图 层类型替代它么?一旦被创建,我们就无法代替这个图层了。但是如果我们继承了UIView,那我们就可以重写+layerClass方法使得在创建的时候 能返回一个不同的图层子类。UIView会在初始化的时候调用+layerClass方法,然后用它的返回类型来创建宿主图层。
清单6.4 演示了一个UILabel子类LayerLabel用CATextLayer绘制它的问题,而不是调用一般的UILabel使用的较慢的 -drawRect:方法。LayerLabel示例既可以用代码实现,也可以在Interface Builder实现,只要把普通的标签拖入视图之中,然后设置它的类是LayerLabel就可以了。
清单6.4 使用CATextLayer的UILabel子类:LayerLabel
#import "LayerLabel.h"#import @implementation LayerLabel+ (Class)layerClass{ //this makes our label create a CATextLayer //instead of a regular CALayer for its backing layer return [CATextLayer class];}- (CATextLayer *)textLayer{ return (CATextLayer *)self.layer;}- (void)setUp{ //set defaults from UILabel settings self.text = self.text; self.textColor = self.textColor; self.font = self.font; //we should really derive these from the UILabel settings too //but that's complicated, so for now we'll just hard-code them [self textLayer].alignmentMode = kCAAlignmentJustified; ? [self textLayer].wrapped = YES; [self.layer display];}- (id)initWithFrame:(CGRect)frame{ //called when creating label programmatically if (self = [super initWithFrame:frame]) { [self setUp]; } return self;}- (void)awakeFromNib{ //called when creating label using Interface Builder [self setUp];}- (void)setText:(NSString *)text{ super.text = text; //set layer text [self textLayer].string = text;}- (void)setTextColor:(UIColor *)textColor{ super.textColor = textColor; //set layer text color [self textLayer].foregroundColor = textColor.CGColor;}- (void)setFont:(UIFont *)font{ super.font = font; //set layer font CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFontRef fontRef = CGFontCreateWithFontName(fontName); [self textLayer].font = fontRef; [self textLayer].fontSize = font.pointSize; ? CGFontRelease(fontRef);}@end如果你运行代码,你会发现文本并没有像素化,而我们也没有设置contentsScale属性。把CATextLayer作为宿主图层的另一好处就是视图自动设置了contentsScale属性。
在这个简单的例子中,我们只是实现了UILabel的一部分风格和布局属性,不过稍微再改进一下我们就可以创建一个支持UILabel所有功能甚至更多功能的LayerLabel类(你可以在一些线上的开源项目中找到)。
如果你打算支持iOS 6及以上,基于CATextLayer的标签可能就有有些局限性。但是总得来说,如果想在app里面充分利用CALayer子类,用+layerClass来创建基于不同图层的视图是一个简单可复用的方法。
CA*Layer(CAShapeLayer--CATextLayer)的更多相关文章
- CA*Layer(CATransformLayer--CAGradientLayer)
CATransformLayer CATransformLayer不同于普通的CALayer,因为它不能显示它自己的内容.只有当存在了一个能作用域子图层的变换它才真正存在.CATransformLay ...
- CA*Layer(CAReplicatorLayer--)
CAReplicatorLayer (反射应用) 指定一个继承于UIView的ReflectionView,它会自动产生内容的反射效果: + (Class)layerClass//我们也可以通过重写V ...
- SSL协议(安全套接层协议)
SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输.Netscape公司在推出第一个Web浏览器的同时,提出了SSL协议标准.其目标是保证 ...
- android图像处理系列之五-- 给图片添加边框(中)
前面一篇讲到给图片加边框的方式,只能给图片加一些有规则的边框,如果想加一些比较精美的效果,就有点麻烦了.下面就给出解决这个问题的思路. 思路是:一些比较精美的花边图片我们是很难用代码控制,就目前本人水 ...
- android图像处理系列之五--给图片添加边框(中)
前面一篇讲到给图片加边框的方式,只能给图片加一些有规则的边框,如果想加一些比较精美的效果,就有点麻烦了.下面就给出解决这个问题的思路. 思路是:一些比较精美的花边图片我们是很难用代码控制,就目前本人水 ...
- csv表格处理(下)--纯JS解析导入csv
多日前的上篇介绍了csv表格,以及JS结合后端PHP解析表格填充表单的方法.其中csv转换成二维数组的时候逻辑比较复杂多坑,幸好PHP有丰富的库函数来处理,而现在用JS解析的话就没有那么幸运了,一切都 ...
- iOS:实现图片的无限轮播(二)---之使用第三方库SDCycleScrollView
iOS:实现图片的无限轮播(二)---之使用第三方库SDCycleScrollView 时间:2016-01-19 19:13:43 阅读:630 评论:0 收藏:0 ...
- 操作系统学习笔记(五)--CPU调度
由于第四章线程的介绍没有上传视频,故之后看书来补. 最近开始学习操作系统原理这门课程,特将学习笔记整理成技术博客的形式发表,希望能给大家的操作系统学习带来帮助.同时盼望大家能对文章评论,大家一起多多交 ...
- IOS 网络浅析-(十三 SDWebImage 实用技巧)
IOS 网络浅析-(十三 SDWebImage 实用技巧) 首先让我描述一下为了什么而产生的实用技巧.(在TableView.CollectionView中)当用户所处环境WiFi网速不够快(不能立即 ...
随机推荐
- WCF入门教程:WCF基础知识问与答(转)
学习WCF已有近两年的时间,其间又翻译了Juval的大作<Programming WCF Services>,我仍然觉得WCF还有更多的内容值得探索与挖掘.学得越多,反而越发觉得自己所知太 ...
- 由于 add 运算符中“Chinese_PRC_CI_AS”和“Chinese_PRC_CS_AS_WS”之间的排序规则冲突
有一个字段的排序规则是 Chinese_PRC_CS_AS_WS,字符串连接的时候报错. 处理方案 cast(columnName as varbinary) 即可
- linux设备驱动归纳总结(七):1.时间管理与内核延时【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxx ...
- grads 绘制仿matlab色标效果
http://bbs.06climate.com/forum.php?mod=viewthread&tid=38391&page=1#pid530730
- CSS选择器无法找到td
.table > tr > td <----这样无法找到td 因为table在浏览器下会自动生成tbody,这样即可 .table > tbody > tr > ...
- oracle 存储过程发邮件
CREATE OR REPLACE PROCEDURE PROCSENDEMAIL(P_TXT VARCHAR2, ...
- DBLINK的session无法关闭,报异常!
------解决方法-------------------------------------------------------- --ALTER SESSION alter session clo ...
- java利用zxing编码解码一维码与二维码
最近琢磨了一下二维码.一维码的编码.解码方法,感觉google的zxing用起来还是比较方便. 本人原创,欢迎转载,转载请标注原文地址:http://wallimn.iteye.com/blog/20 ...
- IOS中用UIStoryBoard类初始化/跳转控制器
1.空工程中通过创建storyboard文件加载页面 //获取Main.storyboardUIStoryboard *mainStory = [UIStoryboard storyboardWi ...
- Mootools插件-闪烁的标题
转自:http://www.cnblogs.com/see7di/archive/2012/10/09/2716024.html 回想起来,我已经好久没有写点啥了,尤其是关于Mootools方面的东西 ...