CALayer 知识:创建带阴影效果的圆角图片图层和创建自定义绘画内容图层

效果如下:

KMLayerDelegate.h

1 #import <UIKit/UIKit.h>
2 
3 @interface KMLayerDelegate : NSObject
4 
5 @end

KMLayerDelegate.m

 1 #import "KMLayerDelegate.h"
 2 
 3 @implementation KMLayerDelegate
 4 
 5 /**
 6  *  根据角度,获取对应的弧度
 7  *
 8  *  @param degree 角度
 9  *
10  *  @return 对应的弧度
11  */
12 static inline double radian(double degree) {
13     return degree * M_PI/180;
14 }
15 
16 /**
17  *  绘画着色模式内容;绘画预定宽高大小的单元格,每个单元格包含两个半圆,分别为『左上角的上半圆』和『右下边的下半圆』
18  *
19  *  @param info    信息
20  *  @param context 上下文
21  */
22 void drawColoredPattern(void *info, CGContextRef context) {
23     CGColorRef dotColor = [UIColor colorWithHue:0.0 saturation:0.0 brightness:0.0 alpha:0.8].CGColor; //圆点颜色;以色彩、饱和度、亮度和不透明度组合的颜色
24     CGColorRef dotShadowColor = [UIColor orangeColor].CGColor; //圆点阴影颜色
25     
26     CGContextSetFillColorWithColor(context, dotColor); //设置填充色
27     CGContextSetShadowWithColor(context, CGSizeMake(2.0, 2.0), 1, dotShadowColor); //设置阴影颜色;以阴影位置偏差为(2.0, 2.0)、模糊效果的 dotShadowColor 作为阴影颜色
28     
29     CGContextAddArc(context, 10.0, 10.0, 10.0, 0.0, radian(180.0), 1); //添加圆点;以居中点为(10.0, 10.0)、半径为10.0、顺时针画0.0到180.0弧度的圆点(即为上半圆),注意0.0弧度为水平线左边位置开始
30     CGContextFillPath(context);
31     
32     CGContextAddArc(context, 30.0, 20.0, 10.0, 0.0, radian(180.0), 0); //添加圆点;以居中点为(30.0, 20.0)、半径为10.0、逆时针画0.0到180.0弧度的圆点(即为下半圆),注意0.0弧度为水平线左边位置开始
33     CGContextFillPath(context);
34 }
35 
36 /**
37  *  绘画内容图层
38  *
39  *  @param layer   当前图层
40  *  @param context 上下文
41  */
42 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
43     //图层背景颜色
44     CGColorRef backgroundColor = [UIColor lightGrayColor].CGColor;
45     CGContextSetFillColorWithColor(context, backgroundColor);
46     CGContextFillRect(context, layer.bounds);
47     
48     static const CGPatternCallbacks callbacks = { 0, &drawColoredPattern, NULL };
49     //绘画连续的单元格,每个单元格的内容由 drawColoredPattern 方法决定
50     CGContextSaveGState(context);
51     CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
52     CGContextSetFillColorSpace(context, patternSpace);
53     CGColorSpaceRelease(patternSpace);
54     
55     CGPatternRef pattern = CGPatternCreate(NULL,
56                                            layer.bounds,
57                                            CGAffineTransformIdentity,
58                                            40.0, //单元格的宽度
59                                            40.0, //单元格的高度
60                                            kCGPatternTilingConstantSpacing,
61                                            true,
62                                            &callbacks);
63     CGFloat alpha = 1.0; //着色模式内容的不透明度
64     CGContextSetFillPattern(context, pattern, &alpha);
65     CGPatternRelease(pattern);
66     CGContextFillRect(context, layer.bounds);
67     CGContextRestoreGState(context);
68 }
69 
70 @end

ViewController.h

1 //#import <UIKit/UIKit.h>
2 #import <QuartzCore/CALayer.h>
3 #import "KMLayerDelegate.h"
4 
5 @interface ViewController : UIViewController
6 @property (strong, nonatomic) KMLayerDelegate *layerDelegate;
7 
8 @end

ViewController.m

  1 #import "ViewController.h"
  2 
  3 static CGFloat const kCornerRadius = 10.0;
  4 static CGFloat const kWidthOfIcon = 120.0;
  5 static CGFloat const kLineWidth = 5.0;
  6 static CGFloat const kBaseNumber = 24; ///< 24等分法
  7 
  8 @interface ViewController ()
  9 - (void)createShadowCornerImage:(UIImage *)image withRootLayer:(CALayer *)rootLayer;
 10 - (void)createCustomDrawingLayer:(CALayer *)rootLayer;
 11 - (void)createSuccessIconDrawingLayer:(CALayer *)rootLayer;
 12 - (void)createWarningIconDrawingLayer:(CALayer *)rootLayer;
 13 - (void)createErrorIconDrawingLayer:(CALayer *)rootLayer;
 14 - (void)layoutUI;
 15 @end
 16 
 17 @implementation ViewController
 18 
 19 - (void)viewDidLoad {
 20     [super viewDidLoad];
 21     
 22     [self layoutUI];
 23 }
 24 
 25 - (void)didReceiveMemoryWarning {
 26     [super didReceiveMemoryWarning];
 27     // Dispose of any resources that can be recreated.
 28 }
 29 
 30 /**
 31  *  创建带阴影效果的圆角图片图层
 32  *
 33  *  @param image     图片
 34  *  @param rootLayer 根图层
 35  */
 36 - (void)createShadowCornerImage:(UIImage *)image withRootLayer:(CALayer *)rootLayer {
 37     // 子图层(图片的阴影图层)
 38     CALayer *subLayer = [CALayer layer];
 39     subLayer.frame = CGRectMake(20.0, 40.0, 150.0, 150.0);
 40     subLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
 41     subLayer.cornerRadius = kCornerRadius;
 42     subLayer.borderColor = [UIColor blackColor].CGColor;
 43     subLayer.borderWidth = 2.0;
 44     subLayer.shadowColor = [UIColor blackColor].CGColor; // 设置阴影颜色
 45     subLayer.shadowOpacity = 0.7; // 设置阴影不透明度
 46     subLayer.shadowOffset = CGSizeMake(4.0, 3.0); // 设置阴影位置偏差
 47     subLayer.shadowRadius = 5.0; // 设置阴影圆角半径
 48     [rootLayer addSublayer:subLayer];
 49     
 50     // 子图层的子图层(图片的内容图层)
 51     CALayer *imageLayer = [CALayer layer];
 52     imageLayer.frame = subLayer.bounds;
 53     imageLayer.contents = (id)image.CGImage;
 54     imageLayer.masksToBounds = YES; // 设置标示剪切界限;内容图层需设置为 YES,才能有圆角效果
 55     imageLayer.cornerRadius = kCornerRadius;
 56     CGAffineTransform affineTransform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.8, 0.8), CGAffineTransformMakeRotation(M_PI_4/9)); // 合并缩放和旋转效果;以0.8比例居中缩放,以45度/9=5度的角度顺时针旋转
 57     imageLayer.affineTransform = affineTransform;
 58     [subLayer addSublayer:imageLayer];
 59 }
 60 
 61 /**
 62  *  创建自定义绘画内容图层(KMLayerDelegate)
 63  *
 64  *  @param rootLayer 根图层
 65  */
 66 - (void)createCustomDrawingLayer:(CALayer *)rootLayer {
 67     CALayer *drawingLayer = [CALayer layer];
 68     drawingLayer.frame = CGRectMake(200.0, 40.0, 150.0, 150.0);
 69     drawingLayer.backgroundColor = [UIColor orangeColor].CGColor; // 背景颜色会被内容图层遮住,所以最终呈现的以内容图层为准
 70     drawingLayer.masksToBounds = YES; // 设置标示剪切界限;内容图层需设置为 YES,才能有圆角效果
 71     drawingLayer.cornerRadius = kCornerRadius;
 72     drawingLayer.borderColor = [UIColor blackColor].CGColor;
 73     drawingLayer.borderWidth = 2.0;
 74     drawingLayer.shadowColor = [UIColor darkGrayColor].CGColor; // 设置阴影颜色
 75     drawingLayer.shadowOpacity = 0.8; // 设置阴影不透明度
 76     drawingLayer.shadowOffset = CGSizeMake(8.0, 6.0); // 设置阴影位置偏差
 77     drawingLayer.shadowRadius = 5.0; // 设置阴影圆角半径
 78     
 79     _layerDelegate = [KMLayerDelegate new];
 80     drawingLayer.delegate = _layerDelegate;
 81     [drawingLayer setNeedsDisplay]; // 这里必须调用方法 setNeedsDisplay,才会触发委托代理方法 drawLayer:
 82     [rootLayer addSublayer:drawingLayer];
 83 }
 84 
 85 /**
 86  *  创建绿色成功图标内容图层
 87  *
 88  *  @param rootLayer 根图层
 89  */
 90 - (void)createSuccessIconDrawingLayer:(CALayer *)rootLayer {
 91     // 成功图标颜色:绿色
 92     UIColor *const color = [UIColor colorWithRed:0.000 green:1.000 blue:0.502 alpha:1.000];
 93     
 94     // 贝塞尔曲线路径;开始画圆
 95     UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0.0, 0.0, kWidthOfIcon, kWidthOfIcon)];
 96     // 然后以三点形成「打勾」效果
 97     [path moveToPoint:CGPointMake(kWidthOfIcon/kBaseNumber*4, kWidthOfIcon/kBaseNumber*12)];
 98     CGPoint p1 = CGPointMake(kWidthOfIcon/kBaseNumber*8, kWidthOfIcon/kBaseNumber*16);
 99     [path addLineToPoint:p1];
100     
101     CGPoint p2 = CGPointMake(kWidthOfIcon/kBaseNumber*18, kWidthOfIcon/kBaseNumber*6);
102     [path addLineToPoint:p2];
103     
104     // 子图层
105     CAShapeLayer *subLayer = [CAShapeLayer layer];
106     subLayer.frame = CGRectMake(125.0, 210.0, kWidthOfIcon, kWidthOfIcon);
107     subLayer.path = path.CGPath;
108     subLayer.lineWidth = kLineWidth; // 线条宽度
109     subLayer.strokeColor = color.CGColor; // 线条颜色
110     subLayer.fillColor = [UIColor clearColor].CGColor; //清除填充色
111     [rootLayer addSublayer:subLayer];
112 }
113 
114 /**
115  *  创建黄色警告图标内容图层
116  *
117  *  @param rootLayer 根图层
118  */
119 - (void)createWarningIconDrawingLayer:(CALayer *)rootLayer {
120     CGFloat centerOfWidth = (kWidthOfIcon - kLineWidth)/2;
121     // 警告图标颜色:黄色
122     UIColor *const color = [UIColor colorWithRed:1.000 green:0.800 blue:0.400 alpha:1.000];
123     
124     // 贝塞尔曲线路径;开始画圆
125     UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0.0, 0.0, kWidthOfIcon, kWidthOfIcon)];
126     // 然后画感叹号
127     [path moveToPoint:CGPointMake(centerOfWidth, kWidthOfIcon/kBaseNumber*4)];
128     CGPoint p1 = CGPointMake(centerOfWidth, kWidthOfIcon/kBaseNumber*16);
129     [path addLineToPoint:p1];
130     
131     [path moveToPoint:CGPointMake(centerOfWidth, kWidthOfIcon/kBaseNumber*19)];
132     [path addArcWithCenter:CGPointMake(centerOfWidth, kWidthOfIcon/kBaseNumber*19) radius:3.0 startAngle:0 endAngle:M_PI*2 clockwise:YES];
133     
134     // 子图层
135     CAShapeLayer *subLayer = [CAShapeLayer layer];
136     subLayer.frame = CGRectMake(125.0, 360.0, kWidthOfIcon, kWidthOfIcon);
137     subLayer.path = path.CGPath;
138     subLayer.lineWidth = kLineWidth; // 线条宽度
139     subLayer.strokeColor = color.CGColor; // 线条颜色
140     subLayer.fillColor = [UIColor clearColor].CGColor; //清除填充色
141     [rootLayer addSublayer:subLayer];
142 }
143 
144 /**
145  *  创建红色错误图标内容图层
146  *
147  *  @param rootLayer 根图层
148  */
149 - (void)createErrorIconDrawingLayer:(CALayer *)rootLayer {
150     CGFloat keyVal1 = kWidthOfIcon/kBaseNumber*6;
151     CGFloat keyVal2 = kWidthOfIcon/kBaseNumber*18;
152     // 失败图标颜色:红色
153     UIColor *const color = [UIColor colorWithRed:1.000 green:0.400 blue:0.400 alpha:1.000];
154     
155     // 贝塞尔曲线路径;开始画圆
156     UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0.0, 0.0, kWidthOfIcon, kWidthOfIcon)];
157     // 然后画交叉号
158     CGPoint p1 =  CGPointMake(keyVal1, keyVal1);
159     [path moveToPoint:p1];
160     
161     CGPoint p2 =  CGPointMake(keyVal2, keyVal2);
162     [path addLineToPoint:p2];
163     
164     CGPoint p3 =  CGPointMake(keyVal2, keyVal1);
165     [path moveToPoint:p3];
166     
167     CGPoint p4 =  CGPointMake(keyVal1, keyVal2);
168     [path addLineToPoint:p4];
169     
170     // 子图层
171     CAShapeLayer *subLayer = [CAShapeLayer layer];
172     subLayer.frame = CGRectMake(125.0, 510.0, kWidthOfIcon, kWidthOfIcon);
173     subLayer.path = path.CGPath;
174     subLayer.lineWidth = kLineWidth; // 线条宽度
175     subLayer.strokeColor = color.CGColor; // 线条颜色
176     subLayer.fillColor = [UIColor clearColor].CGColor; //清除填充色
177     [rootLayer addSublayer:subLayer];
178 }
179 
180 - (void)layoutUI {
181     //根图层
182     CALayer *rootLayer = self.view.layer;
183     rootLayer.backgroundColor = [UIColor colorWithRed:0.769 green:0.940 blue:0.943 alpha:1.000].CGColor;
184     rootLayer.cornerRadius = 40.0;
185     
186     [self createShadowCornerImage:[UIImage imageNamed:@"Emoticon_tusiji_icon2"]
187                     withRootLayer:rootLayer];
188     [self createCustomDrawingLayer:rootLayer];
189     [self createSuccessIconDrawingLayer:rootLayer];
190     [self createWarningIconDrawingLayer:rootLayer];
191     [self createErrorIconDrawingLayer:rootLayer];
192 }
193 
194 @end
原文地址:https://www.cnblogs.com/huangjianwu/p/4679026.html