iOS動(dòng)畫篇:自定義View

引言

iOS動(dòng)畫篇:核心動(dòng)畫中講到如何給一個(gè)視圖添加動(dòng)畫效果仑荐,但是其僅局限在系統(tǒng)控件的具有動(dòng)畫效果的屬性雕拼。假設(shè)現(xiàn)在我們要做一個(gè)空心圓形的進(jìn)度條,隨著進(jìn)度的變化具有對(duì)應(yīng)的動(dòng)畫效果粘招,這時(shí)候就需要去自定義一個(gè)圓形的View啥寇,并實(shí)現(xiàn)其形狀隨進(jìn)度屬性的變化而變化,使用Quartz2D就可以輕松滿足此需求洒扎。

什么是Quartz2D

Quartz2D是iOS和OSX中的一個(gè)二維繪圖引擎辑甜,這組API具有許多強(qiáng)大的功能,如:圖形的繪制袍冷、透明層磷醋、陰影、顏色管理胡诗、反鋸齒邓线、PDF文檔的管理等等淌友。

本文主要介紹了Quartz2D主要相關(guān)概念,描述其中的圖形繪制部分(通過路徑繪制圖形)骇陈,以實(shí)現(xiàn)自定義View震庭。本文不對(duì)Quartz2D的基礎(chǔ)過多提及,如果讀者需要更深入了解Quartz2D你雌,可以Google"Quartz2D編程指南"研讀Quartz2D系列譯文器联。

相關(guān)概念

使用Quartz2D來繪制圖形,需要知道的相關(guān)概念:

1匪蝙、Core Graphics

Core Graphic是一套基于C的框架主籍,用于一切繪圖操作,UIKit就是基于Core Graphic實(shí)現(xiàn)的逛球,因此它可以實(shí)現(xiàn)比UIKit更底層的功能千元。


Core Graphic

  Core Graphic使用Quartz2D作為繪圖引擎,因此Quartz2D其實(shí)是Core Graphic的一部分颤绕,這兩個(gè)名詞密不可分幸海。

2、圖形上下文

畫畫需要畫布奥务,Core Graphics工作是的“畫布”就是圖形上下文物独,它決定圖形繪制成什么樣子,并繪制到哪里去氯葬。在“畫布”中挡篓,每個(gè)連續(xù)的繪制操作都可以看成添加一個(gè)“圖層”到畫布上,在運(yùn)行中我們可以通過額外的繪制操作來疊加更多“圖層”來形成復(fù)雜的圖形帚称。
  推薦使用UIView自動(dòng)為我們準(zhǔn)備好的圖形上下文官研,因?yàn)樽远x上下文會(huì)降低內(nèi)存的使用效率,導(dǎo)致性能下降闯睹。當(dāng)需要我們調(diào)用UIGraphicsGetCurrentContext()來獲取圖形上下文戏羽。

3、路徑

相信很多人都臨摹過書法楼吃,在一張薄薄的紙上照著書法家的筆跡來書寫始花,這個(gè)“筆跡”就可以看成路徑,通過確定的路徑孩锡,可以確定繪圖的形狀酷宵、渲染的區(qū)域等等。
  通過創(chuàng)建路徑并加入到上下文中渲染就能繪制出想要的圖形躬窜。

創(chuàng)建路徑有以下三種方式:

1.使用CGContextRef創(chuàng)建忧吟,如CGContextAddArc

這種方式是直接對(duì)圖形上下文進(jìn)行操作,常用的方法有:

   CGContextBeginPath //開始畫路徑
   CGContextMoveToPoint //移動(dòng)到某一點(diǎn)
   CGContexAddLineToPoint //畫直線
   CGContexAddCurveToPoint //畫餅圖
   CGContexAddEllipseInRect //畫橢圓
   CGContexAddArc //畫圓
   CGContexAddRect //畫方框
   CGContexClosePath //封閉當(dāng)前路徑
2.使用CGPathRef創(chuàng)建斩披,如CGPathAddArc

使用方法一繪制路徑后將清空?qǐng)D形上下文溜族,如果我們想保存路徑來復(fù)用,可以使用Quartz提供的CGPath函數(shù)集合來創(chuàng)建可復(fù)用的路徑對(duì)象垦沉。

常用的函數(shù)如下:

   CGPathCreateMutable
   CGPathMoveToPoint
   CGPathAddLineToPoint
   CGPathAddCurveToPoint
   CGPathAddEllipseInRect
   CGPathAddArc
   CGPathAddRect
   CGPathCloseSubpath 

這些函數(shù)和上面方法一的一一對(duì)應(yīng)煌抒,可代替之使用。

  CGContextAddPath:添加一個(gè)新的路徑
2.使用UIBezierPath創(chuàng)建厕倍,如bezierPathWithOvalInRect

UIBezierPath存在于UIKit中寡壮,是對(duì)路徑繪制的封裝,和CGContextRef類似讹弯,優(yōu)點(diǎn)是更面向?qū)ο罂黾龋覀兛梢韵癫僮髌胀▽?duì)象一樣對(duì)其進(jìn)行操作。
  在自定義View的時(shí)候组民,一般使用UIBezierPath來創(chuàng)建路徑就能基本滿足我們的需求棒仍,推薦使用。

UIBezierPath的常用方法如下:

  @property(nonatomic) CGFloat lineWidth; //線的寬度
  @property(nonatomic) CGLineCap lineCapStyle; //起點(diǎn)和終點(diǎn)樣式
  @property(nonatomic) CGLineJoin lineJoinStyle; //轉(zhuǎn)角樣式
   //創(chuàng)建path
   + (instancetype)bezierPath;
   //矩形
   + (instancetype)bezierPathWithRect:(CGRect)rect;
   //以矩形框?yàn)榍芯€畫圓
   + (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
   //帶圓角的矩形框
   + (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
   //畫圓弧
   + (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
   //移動(dòng)到某一點(diǎn)
   - (void)moveToPoint:(CGPoint)point;
   //添加直線
   - (void)addLineToPoint:(CGPoint)point;
   //帶一個(gè)基準(zhǔn)點(diǎn)的曲線
   - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
   //帶兩個(gè)基準(zhǔn)點(diǎn)的曲線
   - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
   //封閉路徑
   - (void)closePath;
   //添加新的路徑
   - (void)appendPath:(UIBezierPath *)bezierPath;
   //渲染
   - (void)fill;
   - (void)stroke;
4臭胜、渲染

繪畫的最后一步莫其,它之于繪圖的意義如畫畫的最后上顏料一樣。

渲染分為兩種方式:
 ∷嗜1)填充Fill:將路徑內(nèi)部填充渲染
 ÷叶浮2)描邊Stroke:不填充,只對(duì)路徑進(jìn)行渲染

5仪壮、繪圖狀態(tài)棧

圖形上下文包含一個(gè)繪圖狀態(tài)棧憨颠,默認(rèn)為空。
 』1)保存圖形狀態(tài)時(shí)爽彤,將創(chuàng)建當(dāng)前圖形狀態(tài)的一個(gè)副本并入棧。
 》Ψ小2)還原圖形狀態(tài)時(shí)淫茵,將棧頂?shù)膱D形狀態(tài)推出棧并替換當(dāng)前圖形狀態(tài)。
  使用:調(diào)用CGContextSaveGState來保存蹬跃,CGContextRestoreGState來還原匙瘪。

繪圖的核心步驟

在view上繪制一個(gè)圖形的方式有很多種,表現(xiàn)形式可能不一樣蝶缀,但其實(shí)質(zhì)步驟都是一樣的:
  1)獲取上下文
  2)繪制路徑
  3)添加路徑到上下文
  4)修改圖形狀態(tài)參數(shù)
  5)渲染上下文

下面我們以畫一個(gè)圓形來演示其實(shí)現(xiàn)步驟:

1)使用CGContextRef創(chuàng)建路徑
 //獲取上下文
 CGContextRef ctx = UIGraphicsGetCurrentContext();
 //繪制路徑: 圓形(中心坐標(biāo)200丹喻、200、半徑100翁都、起點(diǎn)弧度0碍论、終點(diǎn)弧度2PI、畫的方向0逆1正)
 CGContextAddArc(ctx, 200, 200, 100, 0, M_PI * 2, 0);
 //修改圖形狀態(tài)參數(shù)
 CGContextSetRGBStrokeColor(ctx, 0.5, 0.5, 0.9, 1.0);//筆顏色
 CGContextSetLineWidth(ctx, 10);//線條寬度
 //渲染上下文
 CGContextStrokePath(ctx);
2)使用CGPathRef創(chuàng)建路徑
 //獲取上下文
 CGContextRef ctx = UIGraphicsGetCurrentContext();
 //創(chuàng)建可變路徑
 CGMutablePathRef path = CGPathCreateMutable();
 //添加圓形到路徑中(所在路徑柄慰、不進(jìn)行變換操作鳍悠、中心坐標(biāo)200税娜、200、起點(diǎn)弧度0藏研、終點(diǎn)弧度2PI敬矩、畫的方向0逆1正)
 CGPathAddArc(path, NULL, 200, 200, 100, 0, M_PI * 2, 1);
 //將路徑添加到上下文
 CGContextAddPath(ctx, path);
 //修改圖形狀態(tài)參數(shù)
 CGContextSetRGBStrokeColor(ctx, 0.5, 0.5, 0.9, 1.0);//筆顏色
 CGContextSetLineWidth(ctx, 10);//線條寬度
 //渲染上下文
 CGContextStrokePath(ctx);
3)使用UIBezierPath創(chuàng)建路徑
 //創(chuàng)建路徑
 UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 200, 200)];
 //修改圖形狀態(tài)參數(shù)
 [[UIColor colorWithRed:0.5 green:0.5 blue:0.9 alpha:1.0] setStroke];//筆顏色
 [path setLineWidth:10];//線條寬度
 //渲染
 [path stroke];

以上三種方式都可以實(shí)現(xiàn)繪制,通過比較我們可以發(fā)現(xiàn)使用UIBezierPath創(chuàng)建路徑的形式是最簡潔且最直觀的蠢挡,推薦使用UIBezierPath弧岳,在以后的動(dòng)畫中我們也將更多地應(yīng)用UIBezierPath到動(dòng)畫的實(shí)現(xiàn)中。

自定義view的步驟

只需簡單兩步即可:

步驟一:新建一個(gè)類业踏,繼承UIView類禽炬。
步驟二:重載drawRect方法,在這個(gè)方法中進(jìn)行繪圖勤家。

以自定義一個(gè)圓形View為例:
  1)新建CircleView類腹尖,繼承UIView類


CircleView.png

  2)在CircleView.m中重載drawRect方法

 - (void)drawRect:(CGRect)rect {

 }

3)畫一個(gè)圓

- (void)drawRect:(CGRect)rect {
    UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 200, 200)];
    [[UIColor colorWithRed:0.5 green:0.5 blue:0.9 alpha:1.0] setStroke];
    [path setLineWidth:10];
    [path stroke];
}

4)創(chuàng)建CircleView的實(shí)例添加到視圖中

 - (void)viewDidLoad {
     [super viewDidLoad];
     CircleView * cricleView = [[CircleView alloc]initWithFrame:self.view.bounds];
     [self.view addSubview:cricleView];
 }

5)效果圖


效果圖.png

  成功畫了一個(gè)圓形,現(xiàn)在只差怎樣讓它“動(dòng)起來”了却紧!

思考

1桐臊、Quartz2D的坐標(biāo)系和UIView的坐標(biāo)系有什么不同?
2晓殊、繪制圖形時(shí)不同路徑使用不同的狀態(tài)參數(shù)渲染需要怎樣操作断凶?
3、怎樣使用CALayer來自定義View巫俺?

next:

如何在自定義View上實(shí)現(xiàn)動(dòng)畫效果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末认烁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子介汹,更是在濱河造成了極大的恐慌却嗡,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘹承,死亡現(xiàn)場(chǎng)離奇詭異窗价,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叹卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門撼港,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骤竹,你說我怎么就攤上這事帝牡。” “怎么了蒙揣?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵靶溜,是天一觀的道長。 經(jīng)常有香客問我,道長罩息,這世上最難降的妖魔是什么嗤详? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮扣汪,結(jié)果婚禮上断楷,老公的妹妹穿的比我還像新娘。我一直安慰自己崭别,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布恐锣。 她就那樣靜靜地躺著茅主,像睡著了一般。 火紅的嫁衣襯著肌膚如雪土榴。 梳的紋絲不亂的頭發(fā)上诀姚,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音玷禽,去河邊找鬼赫段。 笑死,一個(gè)胖子當(dāng)著我的面吹牛矢赁,可吹牛的內(nèi)容都是我干的糯笙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼撩银,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼给涕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起额获,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤够庙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后抄邀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耘眨,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年境肾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剔难。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡准夷,死狀恐怖钥飞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衫嵌,我是刑警寧澤读宙,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站楔绞,受9級(jí)特大地震影響结闸,放射性物質(zhì)發(fā)生泄漏唇兑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一桦锄、第九天 我趴在偏房一處隱蔽的房頂上張望扎附。 院中可真熱鬧,春花似錦结耀、人聲如沸留夜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碍粥。三九已至,卻和暖如春黑毅,著一層夾襖步出監(jiān)牢的瞬間嚼摩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工矿瘦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枕面,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓缚去,卻偏偏與公主長得像潮秘,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子病游,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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

  • Core Graphics Framework是一套基于C的API框架唇跨,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,532評(píng)論 0 20
  • --繪圖與濾鏡全面解析 概述 在iOS中可以很容易的開發(fā)出絢麗的界面效果衬衬,一方面得益于成功系統(tǒng)的設(shè)計(jì)买猖,另一方面得益...
    韓七夏閱讀 2,721評(píng)論 2 10
  • Quartz2D以及drawRect的重繪機(jī)制字?jǐn)?shù)1487 閱讀21 評(píng)論1 喜歡1一、什么是Quartz2D Q...
    PurpleWind閱讀 771評(píng)論 0 3
  • 無論是長篇小說還是短篇小說滋尉,標(biāo)題是吸引我讀它的首要因素玉控,而每次讀完我也會(huì)想想這篇文章到底什么地方扣題?對(duì)于這本《無...
    露琪亞閱讀 442評(píng)論 2 5