我們可以在UIView(UIViewRendering)
的方法- (void)drawRect:(CGRect)rect;
中去繪制一些我們所需要的圖形内斯,如虛線凰狞、圓形、方形以及曲線等等圖形。但在使用drawRect
時有一些需要注意的事項:
- 我們只能在繼承了
UIView
的子類中通過重寫drawRect
方法來繪制圖形端圈。 - 如果需要繪制圖形的子類直接繼承自
UIView
,則子類的drawRect
方法中不需要調(diào)用父類方法[super drawRect:rect]子库;
舱权。如果子類繼承自其他繼承UIView
的View
類,則drawRect
方法中需要調(diào)用父類方法[super drawRect:rect]仑嗅;
宴倍。 -
drawRect
方法不能手動直接調(diào)用,我們可以通過調(diào)用其他方法來實現(xiàn)drawRect
方法的調(diào)用仓技。如:在子類初始化時調(diào)用- (instancetype)initWithFrame:(CGRect)frame
方法鸵贬,且frame
不為CGRectZero
時。 - 我們可以調(diào)用
setNeedsDisplay()
方法或setNeedsDisplayInRect
方法脖捻,但是該方法不會自己調(diào)用drawRect
方法阔逼,而是會標(biāo)記視圖,并在下一次循環(huán)更新的時候讓視圖通過drawRect
來進(jìn)行重繪地沮,前提是rect
不為CGRectZero
嗜浮。
一羡亩、虛線
繪制虛線的基本思路:
- 通過
UIGraphicsGetCurrentContext
來獲取需要處理的上下文線條。
CGContextRef context = UIGraphicsGetCurrentContext();
- 通過
CGContextSetLineWidth
來設(shè)置線條的寬度周伦。
CGContextSetLineWidth(context, 2.0);
- 通過
CGContextSetStrokeColorWithColor
或者CGContextSetRGBStrokeColor
來設(shè)置線條的顏色夕春。
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
- 通過
CGContextSetLineDash
來設(shè)置虛線點的大小以及虛線點間隔大小。其中{3, 1}
表示先畫3個實點再畫1個虛點专挪,即實點多虛點少表示虛線點大且間隔小及志,實點少虛點多表示虛線點小且間隔大。最后的參數(shù)1
代表排列的個數(shù)寨腔。
CGFloat dashArray[] = {3, 1};
CGContextSetLineDash(context, 1, dashArray, 1);
- 然后設(shè)置虛線的起點和終點坐標(biāo)速侈,并且有兩種方法。第一種是通過
CGContextMoveToPoint
設(shè)置線條的起點坐標(biāo)(CGFloat x1, CGFloat y1)
迫卢,通過CGContextAddLineToPoint
設(shè)置線條的終點坐標(biāo)(CGFloat x2, CGFloat y2)
倚搬。第二種設(shè)置坐標(biāo)點數(shù)組,通過CGContextAddLines
添加坐標(biāo)點數(shù)組乾蛤。
第一種:
CGContextMoveToPoint(context, K_PDD_WIDTH, K_HEIGHT*3);
CGContextAddLineToPoint(context, (rect.size.width - K_PDD_WIDTH), K_HEIGHT*3);
第二種:
CGPoint aPoints[2];
aPoints[0] = CGPointMake(K_PDD_WIDTH, K_HEIGHT);
aPoints[1] = CGPointMake((rect.size.width - K_PDD_WIDTH), K_HEIGHT);
CGContextAddLines(context, aPoints, 2);
- 最后通過
CGContextStrokePath
來繪制兩點之間的路徑每界。
CGContextStrokePath(context);
完整代碼:
#define K_HEIGHT 100.0
#define K_PDD_WIDTH 20.0
- (void)drawRect:(CGRect)rect {
//獲得處理的上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//線條寬
CGContextSetLineWidth(context, 2.0);
//線條顏色
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
//畫虛線
CGFloat dashArray[] = {3, 1};//表示先畫3個實點再畫1個虛點,即實點多虛點少表示虛線點大且間隔小家卖,實點少虛點多表示虛線點小且間隔大
CGContextSetLineDash(context, 1, dashArray, 1);//最后的參數(shù)1代表排列的個數(shù)
//起點坐標(biāo)
CGContextMoveToPoint(context, K_PDD_WIDTH, K_HEIGHT*3);
//終點坐標(biāo)
CGContextAddLineToPoint(context, (rect.size.width - K_PDD_WIDTH), K_HEIGHT*3);
//繪制路徑
CGContextStrokePath(context);
}
繪制圖像如下:
二眨层、實線
繪制實線的思路和虛線的思路基本一樣,主要區(qū)別在于需要去掉繪制虛線方法中設(shè)置虛線點大小的方法CGContextSetLineDash
上荡。
完整代碼:(代碼中使用了繪制虛線思路中設(shè)置線條顏色和設(shè)置起點終點坐標(biāo)的第二種方法)
- (void)firstDrawStraightLineWithRect:(CGRect)rect {
//獲得處理的上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//線條寬
CGContextSetLineWidth(context, 1.0);
//線條顏色
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0); //設(shè)置線條顏色第一種方法
//坐標(biāo)點數(shù)組
CGPoint aPoints[2];
aPoints[0] = CGPointMake(K_PDD_WIDTH, K_HEIGHT);
aPoints[1] = CGPointMake((rect.size.width - K_PDD_WIDTH), K_HEIGHT);
//添加線 points[]坐標(biāo)數(shù)組趴樱,和count大小
CGContextAddLines(context, aPoints, 2);
//根據(jù)坐標(biāo)繪制路徑
CGContextDrawPath(context, kCGPathStroke);
}
繪制圖像如下:
三、繪制文本
直接上代碼酪捡,其中有注釋:
- (void)drawRect:(CGRect)rect {
NSString * text = @"這是一段繪制文本叁征、這是一段繪制文本、這是一段繪制文本逛薇、這是一段繪制文本捺疼、這是一段繪制文本、這是一段繪制文本永罚、這是一段繪制文本”;
//文本段落樣式
NSMutableParagraphStyle * textStyle = [[NSMutableParagraphStyle alloc] init];
textStyle.lineBreakMode = NSLineBreakByWordWrapping;//結(jié)尾部分的內(nèi)容以……方式省略 ( "...wxyz" ,"abcd..." ,"ab…yz”)
textStyle.alignment = NSTextAlignmentLeft;//文本對齊方式:(左帅涂,中,右尤蛮,兩端對齊媳友,自然)
textStyle.lineSpacing = 8; //字體的行間距
textStyle.firstLineHeadIndent = 35.0; //首行縮進(jìn)
textStyle.headIndent = 0.0; //整體縮進(jìn)(首行除外)
textStyle.tailIndent = 0.0; //尾部縮進(jìn)
textStyle.minimumLineHeight = 40.0; //最低行高
textStyle.maximumLineHeight = 40.0; //最大行高
textStyle.paragraphSpacing = 15; //段與段之間的間距
textStyle.paragraphSpacingBefore = 22.0f; // 段首行空白空間
textStyle.baseWritingDirection = NSWritingDirectionLeftToRight; //從左到右的書寫方向
textStyle.lineHeightMultiple = 15;
textStyle.hyphenationFactor = 1; //連字屬性 在iOS,唯一支持的值分別為0和1
//文本屬性
NSMutableDictionary *textAttributes = [[NSMutableDictionary alloc] init];
//段落樣式
[textAttributes setValue:textStyle forKey:NSParagraphStyleAttributeName];
//字體名稱和大小
[textAttributes setValue:[UIFont systemFontOfSize:20.0] forKey:NSFontAttributeName];
//顏色
[textAttributes setValue:[UIColor redColor] forKey:NSForegroundColorAttributeName];
//繪制文字
[text drawInRect:rect withAttributes:textAttributes];
}
繪制圖像如下:
四产捞、繪制圖片
繪制圖片的基本思路:
- 通過
UIGraphicsGetCurrentContext
來獲取需要處理的上下文線條醇锚。
CGContextRef context = UIGraphicsGetCurrentContext();
- 通過
CGContextSaveGState
來保存初始狀態(tài)。
CGContextSaveGState(context);
- 利用
CGContextTranslateCTM
來移動圖形上下文。
CGContextTranslateCTM(context, 50.0, 80.0);
- 利用
CGContextScaleCTM
來縮放圖形上下文焊唬。
CGContextScaleCTM(context, 0.9, 0.9);
- 利用
CGContextRotateCTM
來進(jìn)行旋轉(zhuǎn)操作恋昼。
CGContextRotateCTM(context, M_PI_4 / 4);
- 設(shè)置繪制圖片的尺寸大小。
UIImage *image = [UIImage imageNamed:@"512”];
CGRect rectImage = CGRectMake(0.0, 0.0, rect.size.width, (rect.size.width*image.size.height/image.size.width));
- 設(shè)置繪制圖片展示的三種狀態(tài):
- 在
rect
范圍內(nèi)完整顯示圖片:
[image drawInRect:rectImage];
- 圖片上下顛倒:
CGContextDrawImage(context, rectImage, image.CGImage);
- 圖片上下顛倒并拼接填充:
CGContextDrawTiledImage(context, rectImage, image.CGImage);
- 最后恢復(fù)到初始狀態(tài)赶促。
CGContextRestoreGState(context);
完整代碼:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//保存初始狀態(tài)(壓棧操作液肌,保存一份當(dāng)前圖形上下文)
CGContextSaveGState(context);
//圖形上下文移動{x,y}
CGContextTranslateCTM(context, 50.0, 80.0);
//圖形上下文縮放{x,y}
CGContextScaleCTM(context, 0.9, 0.9);
//旋轉(zhuǎn)
CGContextRotateCTM(context, M_PI_4 / 4);
//需要繪制的圖片
UIImage *image = [UIImage imageNamed:@"512”];
CGRect rectImage = CGRectMake(0.0, 0.0, rect.size.width, (rect.size.width*image.size.height/image.size.width));
//三種方式繪制圖片
// 1、在rect范圍內(nèi)完整顯示圖片-正常使用
[image drawInRect:rectImage];
// 2鸥滨、圖片上下顛倒
// CGContextDrawImage(context, rectImage, image.CGImage);
// 3嗦哆、圖片上下顛倒并拼接填充
// CGContextDrawTiledImage(context, rectImage, image.CGImage);
//恢復(fù)到初始狀態(tài)(出棧操作,恢復(fù)一份當(dāng)前圖形上下文)
CGContextRestoreGState(context);
}
只展示一種繪制圖片:
五婿滓、圓形圖片
繪制圓形圖片的基本思路:
- 獲取
UIView
的圖形上下文對象老速; - 利用
CG_EXTERN void CGContextAddArc(CGContextRef cg_nullable c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
方法在上下文對象上繪制一個圓形路徑。其中參數(shù)(x, y)
是圓弧的中心凸主;radius
是它的半徑橘券;startAngle
是與圓弧第一個端點的夾角;endAngle
是到弧的第二個端點的角度卿吐;startAngle
和endAngle
用弧度表示旁舰;如果圓弧是順時針畫的,clockwise
是1嗡官,否則是0鬓梅; - 利用
CGContextClip
方法來裁剪出上下文的顯示區(qū)域,即只有在被裁減出的區(qū)域內(nèi)繪制的圖形才會顯示谨湘; - 把圖片繪制到上下文上。
完整代碼:
- (void)drawRect:(CGRect)rect {
//獲取上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//畫一個上下文顯示的區(qū)域
CGContextAddArc(context, rect.size.width/2, rect.size.height/2, rect.size.width/2, 0, 2 *M_PI, 1);
//裁剪上下文的顯示區(qū)域
CGContextClip(context);
//獲取圖片
UIImage* image1 = [UIImage imageNamed:@"512”];
//繪制到上下文上
[image1 drawInRect:rect];
}
繪制圓角圖片如下:
六芥丧、圓形
繪制圓形的思路和繪制圓形圖片一樣紧阔,直接上代碼:
#define K_R 150.0
#define K_PDD 10.0
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//背景顏色設(shè)置
[[UIColor greenColor] set];
CGContextFillRect(context, rect);
CGContextSetLineWidth(context, 2.0);
//畫虛線
CGFloat dashArray[] = {3, 1};
CGContextSetLineDash(context, 1, dashArray, 1);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
CGContextAddArc(context,
K_PDD+K_R/2, K_R*2+20, K_R/2, 0, 2 * M_PI, 0);
CGContextDrawPath(context, kCGPathFillStroke);
}
繪制圖形效果為下圖中左下角圓形圖案:
七、橢圓形
完整代碼:
#define K_H 100.0
#define K_PDD 10.0
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//背景顏色設(shè)置
[[UIColor whiteColor] set];
CGContextFillRect(context, rect);
//實線橢圓
CGRect rectRing = CGRectMake(K_PDD, K_PDD, (rect.size.width - K_PDD * 2), K_H);
CGContextSetLineWidth(context, 1.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextAddEllipseInRect(context, rectRing);
CGContextDrawPath(context, kCGPathStroke);
//虛線橢圓
rectRing = CGRectMake(K_PDD, K_H+K_PDD*2, (rect.size.width - K_PDD * 2), K_H);
CGFloat dashArray[] = {2, 6};
CGContextSetLineDash(context, 1, dashArray, 2);
CGContextSetLineWidth(context, 1.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
//填充顏色
CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
CGContextAddEllipseInRect(context, rectRing);
CGContextDrawPath(context, kCGPathStroke);
CGContextFillPath(context);
//填充橢圓
rectRing = CGRectMake(K_PDD, K_H*2+K_PDD*3, (rect.size.width - K_PDD * 2), K_H);
CGContextSetLineWidth(context, 1.0);
//填充顏色
CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
CGContextAddEllipseInRect(context, rectRing);
CGContextFillPath(context);
}
繪制圖形效果如下:
八续担、扇形
扇形是圓形的一部分擅耽,所以在繪制的時候可以利用CGContextAddArc
方法來設(shè)置扇形的圓弧路徑,并添加原點為起始點開始繪制物遇。即設(shè)置為:
CGContextAddArc(context, R, R, R/2, (-60 * M_PI / 180), (-120 * M_PI / 180), 1);
(-60 * M_PI / 180)
, (-120 * M_PI / 180)
為兩個端點的角度乖仇。最后一位參數(shù)表示如果圓弧是順時針畫的,clockwise
是1询兴,否則是0乃沙。
完整代碼:
#define K_PDD 10.0
@implementation FanshapedView
- (void)drawRect:(CGRect)rect {
CGFloat R = (CGRectGetWidth(self.frame)-K_PDD*2)/2;
CGContextRef context = UIGraphicsGetCurrentContext();
//背景顏色設(shè)置
[[UIColor whiteColor] set];
CGContextFillRect(context, rect);
//實線扇形-順時針-有邊框,有填充
//邊框?qū)挾? CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextMoveToPoint(context, R, R);
//填充顏色
CGContextSetFillColorWithColor(context, [UIColor purpleColor].CGColor);
CGContextAddArc(context, R, R, R/2, (-60 * M_PI / 180), (-120 * M_PI / 180), 1);//如果圓弧是順時針畫的诗舰,“clockwise”是1警儒,否則是0;
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
//實線扇形-逆時針-有邊框,有填充
//邊框?qū)挾? CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextMoveToPoint(context, R, R*2);
//填充顏色
CGContextSetFillColorWithColor(context, [UIColor purpleColor].CGColor);
CGContextAddArc(context, R, R*2, R/2, (-60 * M_PI / 180), (-120 * M_PI / 180), 0);//如果圓弧是順時針畫的,“clockwise”是1蜀铲,否則是0;
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}
繪制扇形如下:
九边琉、正方形
繪制正方形的基本思路:
- 獲取
UIView
的圖形上下文對象; - 設(shè)置邊線寬度记劝;
- 可以添加虛線邊框:
CGFloat dashArray[] = {1, 4};
CGContextSetLineDash(context, 1, dashArray, 2);
- 設(shè)置正方形的四個頂點位置变姨,有三種方法:
- 直接設(shè)置四個頂點:
CGContextMoveToPoint(context, K_X, K_Y);
CGContextAddLineToPoint(context, K_X+K_W, K_Y);
CGContextAddLineToPoint(context, K_X+K_W, K_Y+K_H);
CGContextAddLineToPoint(context, K_X, K_Y+K_H);
CGContextAddLineToPoint(context, K_X, K_Y);
2.利用CGContextAddLines
方法:
CGPoint pointsRect[5] = {CGPointMake(K_X, K_Y), CGPointMake(K_X+K_W, K_Y), CGPointMake(K_X+K_W, K_Y+K_H), CGPointMake(K_X, K_Y+K_H), CGPointMake(K_X, K_Y)};
CGContextAddLines(context, pointsRect, 5);
3.利用CGContextAddRect
方法設(shè)置Rect
大小:
CGContextAddRect(context, CGRectMake(K_X, K_Y, K_W, K_H));
- 使用繪制模式繪制上下文路徑厌丑。
CGContextDrawPath(context, kCGPathFillStroke);
完整代碼:
#define K_X CGRectGetWidth(self.frame)/3
#define K_Y 20
#define K_W CGRectGetWidth(self.frame)/3
#define K_H CGRectGetWidth(self.frame)/3
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//背景顏色設(shè)置
[[UIColor whiteColor] set];
CGContextFillRect(context, rect);
//邊框
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGFloat dashArray[] = {1, 4};//表示先畫1個點再畫4個點(前者小后者大時定欧,虛線點小且間隔大;前者大后者小時蹄衷,虛線點大且間隔杏嵌睢)
CGContextSetLineDash(context, 1, dashArray, 2);//其中的2表示dashArray中的值的個數(shù)
//方法1 正方形起點-終點
// CGContextMoveToPoint(context, K_X, K_Y);
// CGContextAddLineToPoint(context, K_X+K_W, K_Y);
// CGContextAddLineToPoint(context, K_X+K_W, K_Y+K_H);
// CGContextAddLineToPoint(context, K_X, K_Y+K_H);
// CGContextAddLineToPoint(context, K_X, K_Y);
//方法2 正方形起點-終點
CGPoint pointsRect[5] = {CGPointMake(K_X, K_Y), CGPointMake(K_X+K_W, K_Y), CGPointMake(K_X+K_W, K_Y+K_H), CGPointMake(K_X, K_Y+K_H), CGPointMake(K_X, K_Y)};
CGContextAddLines(context, pointsRect, 5);
//方法3 方形起點-終點
// CGContextAddRect(context, CGRectMake(K_X, K_Y, K_W, K_H));
//填充
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
//繪制路徑及填充模式
CGContextDrawPath(context, kCGPathFillStroke);
}
繪制正方形如圖:
十、矩形和菱形
矩形愧口、菱形和正方形繪制方式類似睦番,部分區(qū)別就是:
- 繪制矩形和菱形的四個頂點坐標(biāo)不同。
- 繪制正方形四個頂點的三種方法矩形都可以適用耍属,但第三種不適用于菱形托嚣。
十一、弧線和曲線
弧線和曲線的區(qū)別是:
- 弧線利用
CGContextAddQuadCurveToPoint
方法添加弧線的控制點坐標(biāo)(即弧線起點與弧線相切線和弧線終點與弧線相切線的焦點)和終點坐標(biāo)厚骗。 - 曲線利用
CGContextAddCurveToPoint
方法添加兩個弧線的控制點坐標(biāo)和終點坐標(biāo)示启。
完整代碼:
#define K_PDD 50.0
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//背景顏色設(shè)置
[[UIColor whiteColor] set];
CGContextFillRect(context, rect);
//弧線
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor orangeColor].CGColor);
//起點
CGContextMoveToPoint(context, K_PDD, K_PDD);
//設(shè)置貝塞爾曲線的控制點坐標(biāo){cp1x,cp1y} 終點坐標(biāo){x,y}
CGContextAddQuadCurveToPoint(context, (rect.size.width/2), K_PDD*4, (rect.size.width - K_PDD), K_PDD*2);
//繪制前設(shè)置邊框和填充顏色
[[UIColor redColor] setStroke];
[[UIColor darkGrayColor] setFill];
CGContextDrawPath(context, kCGPathFillStroke);
//曲線
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
//起點坐標(biāo)
CGContextMoveToPoint(context, K_PDD, K_PDD*8);
//設(shè)置貝塞爾曲線的控制點坐標(biāo){cp1x,cp1y} 控制點坐標(biāo){cp2x,cp2y} 終點坐標(biāo){x,y}
CGContextAddCurveToPoint(context, 100.0, 100.0, 200.0, 500.0, (rect.size.width - 10.0), K_PDD*6);
//繪制前設(shè)置邊框和填充顏色
[[UIColor redColor] setStroke];
[[UIColor darkGrayColor] setFill];
CGContextDrawPath(context, kCGPathFillStroke);
}
繪制弧線和曲線圖像如下:
十二、漸變背景顏色
直接上代碼:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClip(context);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGFloat colors[] = {
200.0 / 255.0, 224.0 / 255.0, 244.0 / 0.0, 1.00,
100.0 / 255.0, 156.0 / 255.0, 215.0 / 100.0, 1.00,
0.0 / 255.0, 50.0 / 255.0, 126.0 / 200.0, 1.00,
};
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors) / (sizeof(colors[0]) * 4));
CGColorSpaceRelease(rgb);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0.0,0.0), CGPointMake(0.0, rect.size.height), kCGGradientDrawsBeforeStartLocation);
}
效果:
部分繪制圖形效果請參考完整Demo drawRect繪制圖形