除了直接绘画在屏幕上,UIKit框架还提供了屏幕外的bitmap和PDF图形上下文(graphics contexts)。如果是这类的,那么view的绘画循环是不适合这个情况的。
UIView的绘图循环
当UIView需要第一次显示或者view的一部分需要重绘,uiview的drawRect:方法会被调用进行重绘。
需要重绘的情况:
1. 移动或者去除遮挡你的view的其他view
2. 把hidden属性设为no让其他的隐藏的view重新显示
3. 把view滚动出屏幕,然后又重新进入屏幕
4.主动调用setNeedsDisplay或者setNeedsDisplayInRect方法
UIKit和Core Graphics两个框架都支持绘图:
Core Graphics中涉及绘图的主要有Graphics contexts,Paths,Images and bitmaps,Transparency layers,Colors, pattern colors, and color spacesGradients and shadings等
UIKit中涉及绘图的主要有UIImage,UIColor,UIFont, UIScreen,UIBezierPath等
Graphics contexts
要绘图必须有一个graphics contexts,这个对象可以理解成一个画布,所有的东西都要在这上面进行。drawRect:、drawLayer: inContext:、UIGraphicsBeginImageContextWithOptions这个三个方法中都可以去获得Graphic Context从而绘制图形。
例如我们想画一个矩形,边框是蓝色的,宽度是2,填充红色
这样就存在6种绘图的方式:
方式一:在UIView的 - (void)drawRect:(CGRect)rect方法中用Core Graphics框架去实现
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
CGContextAddRect(ctx, CGRectMake(0, 0, 100, 100));
CGContextDrawPath(ctx, kCGPathFillStroke);
方式二:在UIView的
- (void)drawRect:(CGRect)rect方法中用UIKit框架去实现
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
path.lineWidth = 2;
[[UIColor blueColor] setStroke];
[[UIColor redColor] setFill];
[path stroke];
[path fill];
方式三:在CA Layer的delegate中的
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)
方法中用Core Graphics框架去实现
<pre name="code" class="objc"> //在viewcontroller中添加CALayer
CALayer *myLayer = [CALayer layer];
myLayer.frame = CGRectMake(0, 0, 100, 100);
myLayer.delegate = self;
[self.view.layer addSublayer:myLayer];
[myLayer setNeedsDisplay];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
CGContextAddRect(ctx, CGRectMake(0, 0, 100, 100));
CGContextDrawPath(ctx, kCGPathFillStroke);
方式四:在CA Layer的delegate中的
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)
方法中用UIKit框架去实现 UIGraphicsPushContext(ctx);//将ctx作为当前的context
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
path.lineWidth = 2;
[[UIColor blueColor] setStroke];
[[UIColor redColor] setFill];
[path stroke];
[path fill];
UIGraphicsPopContext();
方式五:用UIGraphicsBeginImageContextWithOptions和UIKit框架去实现
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
UIBezierPath* p = [UIBezierPath bezierPathWithRect:CGRectMake(0,0,100,100)];
[[UIColor redColor] setFill];
[[UIColor blueColor] setStroke];
[p fill];
[p stroke];
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//可以用一个UIImageView去显示
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
iv.image = im;
[self.view addSubview:iv];
方式六:用UIGraphicsBeginImageContextWithOptions和Core Graphics框架去实现
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
CGContextAddRect(ctx, CGRectMake(0, 0, 100, 100));
CGContextDrawPath(ctx, kCGPathFillStroke);
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();