/**
*
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:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
以上1,2推荐;而3,4不提倡
drawRect方法使用注意点:
1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext: 中(类似鱼drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕
*
*
*/
#import "MyView.h"
@implementation MyView
- (void)setRectHeight:(CGFloat)rectHeight{
_rectHeight = rectHeight;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
NSLog(@"快点响应,需要不停的刷新你啊");
// [self drawLines];
// [self lineAnimation];
// [self CGMutablePathRefCreateLine];
[self layerTest];
}
/**
* Quartz2D绘图的代码步骤
*
* 1. 获得图形上下文
2. 拼接路径(下面代码是搞一条线段)
3. 绘制路径
*/
#pragma mark 画线---这种是把所有点的坐标都写在了Context中,他有一块区域来保存这些点。
- (void)drawLines{
// 处理上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 设置线条样式
CGContextSetLineCap(ctx, kCGLineCapSquare);
// 设置线条粗细宽度
CGContextSetLineWidth(ctx, 1.0);
// 设置线条的颜色
CGContextSetRGBFillColor(ctx, 9.0, 10.0, 20.0, 60.0);
// 设置开始路径
CGContextMoveToPoint(ctx, 0, 400);
//设置下一个坐标点
CGContextAddLineToPoint(ctx, 100, 300);
//设置下一个坐标点
CGContextAddLineToPoint(ctx, 230, 400);
//设置下一个坐标点
CGContextAddLineToPoint(ctx, 250, 350);
//设置下一个坐标点
CGContextAddLineToPoint(ctx, 260, 100);
//连接上面定义的坐标点
CGContextStrokePath(ctx);
}
#pragma mark CGMutablePathRef 这种形式更加的直观, 直接把所有的点放入一个path中,然后直接画这个path
// 需要的图形的效果都在path的点上面, 画圆形和四边形都是一样的。
- (void)CGMutablePathRefCreateLine{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 200, 200);
CGPathAddLineToPoint(path, NULL, 220, 220);
CGPathAddLineToPoint(path, NULL, 240, 180);
CGContextAddPath(ctx, path);
//宽度
CGContextSetLineWidth(ctx, 2.0f);
// 颜色
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
// 渲染
CGContextStrokePath(ctx);
// 画圆形图像
CGMutablePathRef pathRound = CGPathCreateMutable();
CGPathAddEllipseInRect(pathRound, NULL, CGRectMake(50, 150, 100, 100));
CGContextAddPath(ctx, pathRound);
CGContextStrokePath(ctx);
// 释放资源
CGPathRelease(path);
CGPathRelease(pathRound);
}
#pragma mark Layer用法。
/**
* layer同时也有zposotion的属性,拥有低的zposition的layer比高的先绘制.
*/
- (void)layerTest{
CAShapeLayer *oneLayer = [CAShapeLayer layer];
oneLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
oneLayer.backgroundColor = [UIColor orangeColor].CGColor;
CAShapeLayer *twoLayer = [CAShapeLayer layer];
twoLayer.frame = CGRectMake(0, 150, self.bounds.size.width, self.bounds.size.height);
twoLayer.backgroundColor = [UIColor clearColor].CGColor;
// 在上面这一个图层中进行画图处理。
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 80, 100);
CGPathAddLineToPoint(path, NULL, 180, 100);
CGPathAddLineToPoint(path, NULL, 180, 200);
CGPathAddLineToPoint(path, NULL, 80, 200);
CGPathAddLineToPoint(path, NULL, 80, 100);
twoLayer.path = path;
twoLayer.lineWidth = 2.0f;
twoLayer.strokeColor = [UIColor redColor].CGColor;
twoLayer.fillColor = [UIColor clearColor].CGColor;
// 添加动画效果
CABasicAnimation *animation = [[CABasicAnimation alloc]init];
animation.duration = 1.0f;
animation.fromValue = @0;
animation.toValue = @1;
[twoLayer addAnimation:animation forKey:@"strokeEnd"];
// 画一个长方形
CAShapeLayer *threeLayer = [CAShapeLayer layer];
threeLayer.backgroundColor = [UIColor clearColor].CGColor;
threeLayer.strokeColor = [UIColor redColor].CGColor;
threeLayer.fillColor = [UIColor redColor].CGColor;
threeLayer.lineWidth = 2.0f;
CGMutablePathRef pathRect = CGPathCreateMutable();
// 带圆角的长方形
for (int i = 0; i<300; i=i+50) {
CGPathAddRoundedRect(pathRect, NULL, CGRectMake(10+i, 200, 20, self.rectHeight), 5, 5);
}
threeLayer.path = pathRect;
if (self.rectHeight < 100) {
[[NSNotificationCenter defaultCenter]postNotificationName:@"rectHeightVal" object:nil];
}
[self.layer addSublayer:oneLayer];
[self.layer addSublayer:twoLayer];
[self.layer addSublayer:threeLayer];
}
#pragma mark touch事件, 判断是否点击这个长方形了,然后回调暴露给外面。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self];
NSLog(@"%@",NSStringFromCGPoint(currentLocation));
// 判断点是否在这些长方体内
}
#pragma mark 设置动画效果 //注意:但凡通过Quartz2D中带有creat/copy/retain方法创建出来的值都必须要释放
- (void)lineAnimation{
CAShapeLayer *graphLayer = [CAShapeLayer layer];
graphLayer.frame = self.bounds;
graphLayer.backgroundColor = [UIColor clearColor].CGColor;
graphLayer.strokeColor = [UIColor redColor].CGColor;
graphLayer.lineWidth = 1;
graphLayer.fillColor = [UIColor clearColor].CGColor;
graphLayer.strokeStart = 0.0f;
graphLayer.strokeEnd = 1.0f;
// 画线
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 20, 400);
int count = 0;
for (int i = 20; i<400; i=i+10) {
if (count%2 == 0) {
CGPathAddLineToPoint(path, nil, i, 400);
}else{
CGPathAddLineToPoint(path, nil, i, 350);
}
count++;
}
graphLayer.path = path;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 10;
animation.fromValue = @0;
animation.toValue = @1;
[graphLayer addAnimation:animation forKey:@"strokeEnd"];
[self.layer addSublayer:graphLayer];
}
@end
调用:
@implementation ViewController{
MyView *myView;
}
- (void)viewDidLoad {
[super viewDidLoad];
myView = [[MyView alloc] init];
myView.frame = CGRectMake(0, 0, 300, 400);
myView.rectHeight = 10.0;
[self.view addSubview:myView];
}
- (IBAction)valChange:(id)sender {
UISlider *mySlider = (UISlider *)sender;
myView.rectHeight = mySlider.value;
}
@end