drawRect方法使用注意事项:
drawRect在以下情况下会被调用:
1、如果在UIView初始化时没有设置rect大小
,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
2、该方法在调用sizeToFit后被调用
,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
( 只能改变frame/bounds 改变center无效)
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
drawRect方法使用注意点:
1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用
,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕
贝塞尔曲线
//只能在drawRect方法中使用
//这里只介绍用法(UIBezierPath.h中有一些绘制基本图形的类方法)
UIBezierPath *path = [UIBezierPath bezierPath];
//线宽
path.lineWidth = 20;
//端点圆角
path.lineCapStyle = kCGLineCapRound;
//线段连接处圆角
path.lineJoinStyle = kCGLineJoinRound;
[path moveToPoint:CGPointMake(100, 200)];
[path addLineToPoint:CGPointMake(100, 400)];
[[UIColor redColor]setStroke];
//[[UIColor redColor]set];边框+填充颜色
//画虚线
CGFloat length[]={4,2};
[path setLineDash:length count:2 phase:0];
[path stroke];//渲染
//[path fill];渲染+填充
图形上下文的矩阵变换
- (void)drawRect:(CGRect)rect {
// 1.获取图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, -100, 100, 200)];
// 矩阵变化:给上下文做矩阵变化,一定要在添加路径之前
// 上下文的平移
CGContextTranslateCTM(ctx, 100, 100);
[[UIColor yellowColor]set];
// 旋转上下文
// 弧度
CGContextRotateCTM(ctx, M_PI_4);
// 缩放
CGContextScaleCTM(ctx, 0.5, 0.5);
// 3.添加路径到上下文中
CGContextAddPath(ctx, path.CGPath);
// 4.渲染
CGContextFillPath(ctx);
}
位图上下文
只要不用到layer的上下文,就不需要自定义view,也不需要重写drawRect方法
1.图片水印
UIImage *img = [UIImage imageNamed:@"img"];
// 1.开启位图上下文
// size:位图上下文尺寸
// opaque:不透明 YES:不透明 NO:透明
// 0 不进行缩放
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0);
// 2.拼接路径
// 2.1绘制图片
[img drawAtPoint:CGPointZero];
// 2.2绘制文字
NSString *str = @"水印文字!!!!!";
[str drawAtPoint:CGPointMake(130, 170) withAttributes:nil];
// 3.从上下文中取出图片
img = UIGraphicsGetImageFromCurrentImageContext();
// 4.关闭上下文
UIGraphicsEndImageContext();
2.利用位图上下文来进行截屏操作
// 开启位图上下文
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
// 获取当前上下文->位图上文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 擦除图片(clearRect 为自定义范围)
//CGContextClearRect(ctx, clearRect);
// 拼接路径
// view上面的内容添加到上下文
// view的图层
// 渲染到上下文
[self.view.layer renderInContext:ctx];
// 获取图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭上下文
UIGraphicsEndImageContext();
//可以将图片保存到沙盒 或者相册
3.利用贝塞尔路径进行图形裁剪
/**
* 图形裁剪
*
* @param imageRect 整个图片大小
* @param clipRect 裁剪范围
* @param clipImage 图要裁剪片
*
* @return 裁剪后图片
*/
- (UIImage *)clipWithImageRect:(CGRect)imageRect clipRect:(CGRect)clipRect clipImage:(UIImage *)clipImage;
{
// 开启位图上下文
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0);
// 拼接路径
// 设置裁剪区域
UIBezierPath *path = [UIBezierPath bezierPathWithRect:clipRect];
[path addClip];
// 绘制图片
[clipImage drawInRect:imageRect];
// 获取当前图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭上下文
UIGraphicsEndImageContext();
return image;
}