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