Auto Layout 与 Core Graphics 技术详解
1. Auto Layout 基础
1.1 约束(Constraints)基础
- 代码方式创建约束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeLeading multiplier:1.0 constant:20.0]; [superview addConstraint:constraint];
NSDictionary *views = @{@"view1": view1, @"view2": view2}; [superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-[view2]-|" options:0 metrics:nil views:views]];
|
1.2 Auto Layout 动画
1 2 3 4
| [UIView animateWithDuration:0.3 animations:^{ constraint.constant = newValue; [view layoutIfNeeded]; }];
|
1.3 Safe Area 和布局指南
1 2 3 4 5
| view.safeAreaLayoutGuide.topAnchor view.safeAreaLayoutGuide.bottomAnchor view.safeAreaLayoutGuide.leadingAnchor view.safeAreaLayoutGuide.trailingAnchor
|
2. Core Graphics 绘图
2.1 基本绘图操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); [[UIColor redColor] setStroke]; CGContextSetLineWidth(context, 2.0); CGContextMoveToPoint(context, 10, 10); CGContextAddLineToPoint(context, 100, 100); CGContextStrokePath(context); }
|
2.2 绘制基本图形
1 2 3 4 5 6 7 8 9
| CGContextAddRect(context, CGRectMake(10, 10, 100, 100));
CGContextAddEllipseInRect(context, CGRectMake(10, 10, 100, 100));
CGFloat radius = 10.0; CGContextAddRoundedRect(context, CGRectMake(10, 10, 100, 100), radius);
|
2.3 渐变和阴影
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| CGGradientRef gradient = CGGradientCreateWithColors( CGColorSpaceCreateDeviceRGB(), (__bridge CFArrayRef)@[(id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor], NULL);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(100, 100), kCGGradientDrawsBeforeStartLocation);
CGContextSetShadowWithColor(context, CGSizeMake(2, 2), 3.0, [UIColor blackColor].CGColor);
|
2.4 图片处理
1 2 3 4 5 6 7
| UIImage *image = [UIImage imageNamed:@"example"]; [image drawInRect:CGRectMake(0, 0, 100, 100)];
CGContextClipToRect(context, CGRectMake(0, 0, 50, 50)); [image drawAtPoint:CGPointZero];
|
3. 性能优化
3.1 Auto Layout 性能优化
- 减少约束数量
- 避免复杂的约束关系
- 适时使用
translatesAutoresizingMaskIntoConstraints = NO
3.2 Core Graphics 性能优化
- 避免频繁重绘
- 使用
drawRect: 的替代方案
- 缓存绘制结果
1 2 3 4 5 6 7 8 9
| - (void)optimizeDrawing { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10]; shapeLayer.path = path.CGPath; shapeLayer.fillColor = [UIColor redColor].CGColor; [self.layer addSublayer:shapeLayer]; }
|
4. 实践案例
4.1 自适应卡片视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| @interface CardView : UIView @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UIImageView *imageView; @end
@implementation CardView
- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setupViews]; [self setupConstraints]; } return self; }
- (void)setupViews { self.titleLabel = [[UILabel alloc] init]; self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:self.titleLabel]; self.imageView = [[UIImageView alloc] init]; self.imageView.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:self.imageView]; }
- (void)setupConstraints { [NSLayoutConstraint activateConstraints:@[ [self.titleLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:8], [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:8], [self.titleLabel.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-8], [self.imageView.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:8], [self.imageView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], [self.imageView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], [self.imageView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] ]]; }
@end
|
4.2 自定义绘制进度条
@interface ProgressView : UIView
@property (nonatomic, assign) CGFloat progress;
@end
@implementation ProgressView
- (void)setProgress:(CGFloat)progress {
_progress = progress;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// 绘制背景
[[UIColor lightGrayColor] setFill];
CGContextFillRect(context, rect);
// 绘制进度
[[UIColor blueColor] setFill];
CGRect progressRect = CGRectMake(0, 0, rect.size.width * self.progress, rect.size.height);
CGContextFillRect(context, progressRect);
// 添加渐变效果
CGGradientRef gradient = CGGradientCreateWithColors(
CGColorSpaceCreateDeviceRGB(),
(__bridge CFArrayRef)@[(id)[UIColor colorWithWhite:1 alpha:0.2].CGColor,
(id)[UIColor clearColor].CGColor],
NULL);
CGContextDrawLinearGradient(context,
gradient,
CGPointMake(0, 0),
CGPointMake(0, rect.size.height),
0);
CGGradientRelease(gradient);
}
@end