iOS------繪圖

iOS的繪圖框架有很多種,我們平常最常用的就是UIKit,其底層是依賴CoreGraphics實現(xiàn)的昨悼,而且絕大多數(shù)的圖形界面也都是由UIKit完成的蝗锥,并且UIImage、NSString率触、UIBezierPath玛追、UIColor等都知道如何繪制自己,也提供了一些方法來滿足我們常用的繪圖需求。除了UIKit痊剖,還有CoreGraphics韩玩、Core Animation,Core Image陆馁,OpenGL ES等多種框架找颓,來滿足不同的繪圖要求。各個框架的大概介紹如:

1.->UIKit:最常用的視圖框架叮贩,封裝度高击狮,都是OC對象

2.->CoreGraphics:主要繪制系統(tǒng),常用于繪制自定義視圖益老,純C的API彪蓬,使用Quartz2D做引擎

3.->Core Animation:提供強大的2D和3D動畫效果

4.->Core Image:給圖片提供各種濾鏡處理,比如高斯模糊捺萌、銳化等

5.->OpenGL ES:主要用于游戲繪制档冬,但他是一套編程規(guī)范,具體由設(shè)備制造商實現(xiàn)

繪圖方式:

繪圖包括兩部分:視圖繪制和視圖布局桃纯。他們實現(xiàn)的功能是不同的酷誓,因為都是在繪制周期中進行繪制的

繪圖周期:1.iOS在運行循環(huán)中會整合所有的繪圖請求,并一次將它們繪制出來? 2.不能在子線程中繪制态坦,也不能進行復(fù)雜的操作盐数,否則會造成主線程卡頓

視圖繪制:調(diào)用UIView的- (void)drawRect:(CGRect)rect方法進行繪制。如果調(diào)用一個視圖的-(void)setNeedsDisplay方法伞梯,那么該視圖就被標記為重新繪制玫氢,并且會在下一次繪制周期中重新繪制,自動調(diào)用- (void)drawRect:(CGRect)rect方法

視圖布局:調(diào)用UIView的-(void)layoutSubviews方法谜诫。如果調(diào)用一個視圖的-(void)setNeedsLayout方法漾峡,那么該視圖就被標記為需要重新布局,UIKit會自動調(diào)用-(void)layoutSubviews方法及其子視圖的-(void)layoutSubviews

重點:在繪圖時猜绣,我們應(yīng)該盡量多的使用布局,少使用繪制敬特,是因為布局使用的是GPU掰邢,而繪制使用的是CPU。GPU對于圖形處理有優(yōu)勢伟阔,而CPU要處理的事情較多辣之,且不擅長處理圖形,所以盡量使用GPU來處理圖形皱炉。

繪圖狀態(tài)切換

iOS的繪圖有多種對應(yīng)的狀態(tài)切換怀估,比如:比如:pop/push、save/restore、context/imageContext和CGPathRef/UIBezierPath等多搀,下面分別進行介紹:

1.->pop/push

設(shè)置繪圖的上下文環(huán)境(context)

push:UIGraphicsPushContext(context)把context壓入棧中歧蕉,并把context設(shè)置為當前繪圖上下文

pop:UIGraphicsPopContext將棧頂?shù)纳舷挛膹棾觯謴?fù)先前的上下文康铭,但是繪圖狀態(tài)不變

下面的繪圖是黑色

- (void)drawRect:(CGRect)rect{

[[UIColor redColor]setFill];

UIGraphicsPushContext(UIGraphicsGetCurrentContext());

[[UIColor blackColor]setFill];

UIGraphicsPopContext();

UIRectFill(CGRectMake(90, 340, 100, 100));

}

2.save / restore

設(shè)置繪圖的狀態(tài)(state)

save:CGContextSaveGState 壓棧當前的繪圖狀態(tài)惯退,僅僅是繪圖狀態(tài),不是繪圖上下文

restore:恢復(fù)剛才保存的繪圖狀態(tài)

下面繪制的視圖是紅色

- (void)drawRect:(CGRect)rect{

[[UIColor redColor]setFill];

CGContextSaveGState(UIGraphicsGetCurrentContext());

[[UIColor blackColor]setFill];

CGContextRestoreGState(UIGraphicsGetCurrentContext());

UIRectFill(CGRectMake(90, 200, 100, 100));

}

3.context/imageContext

iOS的繪圖必須在一個上下文中繪制从藤,所以在繪制之前要獲取一個上下文催跪。如果是繪制圖片,就需要獲取一個圖片的上下文夷野;如果是繪制其他視圖懊蒸,就需要一個非圖片上下文。對于上下文的理解悯搔,可以認為就是一張畫布骑丸,然后在上面進行繪圖操作。

context:圖形上下文鳖孤,可以通過UIGraphicsGetCurrentContext()獲取當前視圖的上下文

imageContext:圖片上下文者娱,可以通過UIGraphicsBeginImageContextWithOptions:獲取一個圖片上下文,然后繪制完成后苏揣,調(diào)用UIGraphicsGetImageFromCurrentImageContext獲取繪制的圖片黄鳍,最后要記得關(guān)閉圖片上下文UIGraphicsEndImageContext。

4.CGPathRef / UIBezierPath

圖形的繪制需要繪制一個路徑平匈,然后再把路徑渲染出來框沟,而CGPathRef就是CoreGraphics框架中的路徑繪制類,UIBezierPath是封裝CGPathRef的面向OC的類增炭,使用更加方便忍燥,但是一些高級特性還是不及CGPathRef。

具體繪圖方法

由于iOS常用的繪圖框架有UIKit和CoreGraphics兩個隙姿,所以繪圖的方法也有多種梅垄。

1.圖片類型的上下文:是不需要在- (void)drawRect:(CGRect)rect方法中進行,在一個普通的OC方法中就可以繪制

2.使用UIKit實現(xiàn)

//獲取圖片上下文

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);

//繪圖

UIBezierPath* bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];

[[UIColor blueColor]setFill];

[bezierPath fill];

//從圖片上下文中獲取繪制的圖片

UIImage* image = UIGraphicsGetImageFromCurrentImageContext();

//關(guān)閉圖片上下文

UIGraphicsEndImageContext();

UIImageView* imageView = [[UIImageView alloc]init];

imageView.frame = CGRectMake(0, 64, image.size.width, image.size.height);

[self.view addSubview:imageView];

imageView.image = image;

使用CoreGraphics實現(xiàn):

//獲取圖片上下文

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);

//繪圖

CGContextRef contextRef = UIGraphicsGetCurrentContext();

CGContextAddEllipseInRect(contextRef, CGRectMake(0, 0, 100, 100));

CGContextSetFillColorWithColor(contextRef, [UIColor blueColor].CGColor);

CGContextFillPath(contextRef);

//從圖片上下文中獲取繪制的圖片

UIImage* image = UIGraphicsGetImageFromCurrentImageContext();

//關(guān)閉圖片上下文

UIGraphicsEndImageContext();

UIImageView* imageView = [[UIImageView alloc]init];

[self.view addSubview:imageView];

imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);

imageView.image = image;

2.- (void)drawRect:(CGRect)rect

在UIView子類的- (void)drawRect:(CGRect)rect方法中實現(xiàn)圖形重新繪制输玷,具體繪制步驟如下:

2.1->獲取上下文

2.2->繪制圖形

2.3->渲染圖形

UIKit方法

- (void)drawRect:(CGRect)rect{

UIBezierPath* bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];

[[UIColor blueColor]setFill];

[bezierPath fill];

}

CoreGraphics

- (void)drawRect:(CGRect)rect{

CGContextRef contextRef = UIGraphicsGetCurrentContext();

CGContextAddEllipseInRect(contextRef, CGRectMake(0, 0, 100, 100));

CGContextSetFillColorWithColor(contextRef, [UIColor blueColor].CGColor);

CGContextFillPath(contextRef);

}

3.drawLayer:inContext:

在UIView子類的-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx方法中也可以實現(xiàn)繪圖任務(wù)队丝,他是一個圖層的代理方法,當調(diào)用該方法的時候欲鹏,需要給圖層的delegate設(shè)置代理對象机久。但是代理對象不能是UIView對象,因為UIView對象內(nèi)部已經(jīng)是它內(nèi)部根層的代理對象赔嚎,如果再將他設(shè)置為另一個層的代理對象就會出問題了

一個view被添加到其它view上時膘盖,圖層的變化如下:

3.1->先隱式地把此view的layer的CALayerDelegate設(shè)置成此view

3.2->調(diào)用此view的self.layer的drawInContext方法

3.3->由于drawLayer方法的注釋:If defined, called by the default implementation of -drawInContext:說明了drawInContext里if([self.delegate responseToSelector:@selector(drawLayer:inContext:)])就執(zhí)行drawLayer:inContext:方法胧弛,這里我們因為實現(xiàn)了drawLayer:inContext:所以會執(zhí)行

3.4->[super drawLayer:layer inContext:ctx]會讓系統(tǒng)自動調(diào)用此view的drawRect:方法,至此self.layer畫出來了

3.5->在self.layer上再加一個子layer侠畔,當調(diào)用[layer setNeedsDisplay];時會自動調(diào)用此layer的drawInContext方法

3.6->如果drawRect不重寫结缚,就不會調(diào)用其layer的drawInContext方法,也就不會調(diào)用drawLayer:inContext方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末践图,一起剝皮案震驚了整個濱河市掺冠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌码党,老刑警劉巖德崭,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揖盘,居然都是意外死亡眉厨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門兽狭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憾股,“玉大人,你說我怎么就攤上這事箕慧》颍” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵颠焦,是天一觀的道長斩熊。 經(jīng)常有香客問我,道長伐庭,這世上最難降的妖魔是什么粉渠? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮圾另,結(jié)果婚禮上霸株,老公的妹妹穿的比我還像新娘。我一直安慰自己集乔,他們只是感情好去件,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扰路,像睡著了一般尤溜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幼衰,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天靴跛,我揣著相機與錄音缀雳,去河邊找鬼渡嚣。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的识椰。 我是一名探鬼主播绝葡,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼腹鹉!你這毒婦竟也來了藏畅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤功咒,失蹤者是張志新(化名)和其女友劉穎愉阎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體力奋,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡榜旦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了景殷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溅呢。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猿挚,靈堂內(nèi)的尸體忽然破棺而出咐旧,到底是詐尸還是另有隱情,我是刑警寧澤绩蜻,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布铣墨,位于F島的核電站,受9級特大地震影響辜羊,放射性物質(zhì)發(fā)生泄漏踏兜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一八秃、第九天 我趴在偏房一處隱蔽的房頂上張望碱妆。 院中可真熱鬧,春花似錦昔驱、人聲如沸疹尾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纳本。三九已至,卻和暖如春腋颠,著一層夾襖步出監(jiān)牢的瞬間繁成,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工淑玫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留巾腕,地道東北人面睛。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像尊搬,于是被迫代替她去往敵國和親叁鉴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容