你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS動畫篇:自定義View

iOS動畫篇:自定義View

編輯:IOS開發基礎

引言

在iOS動畫篇:核心動畫中講到如何給一個視圖添加動畫效果,但是其僅局限在系統控件的具有動畫效果的屬性。假設現在我們要做一個空心圓形的進度條,隨著進度的變化具有對應的動畫效果,這時候就需要去自定義一個圓形的View,並實現其形狀隨進度屬性的變化而變化,使用Quartz2D就可以輕松滿足此需求。

什麼是Quartz2D

Quartz2D是iOS和OSX中的一個二維繪圖引擎,這組API具有許多強大的功能,如:圖形的繪制、透明層、陰影、顏色管理、反鋸齒、PDF文檔的管理等等。

本文主要介紹了Quartz2D主要相關概念,描述其中的圖形繪制部分(通過路徑繪制圖形),以實現自定義View。本文不對Quartz2D的基礎過多提及,如果讀者需要更深入了解Quartz2D,可以Google"Quartz2D編程指南"研讀Quartz2D系列譯文。

相關概念

使用Quartz2D來繪制圖形,需要知道的相關概念:

1、Core Graphics

Core Graphic是一套基於C的框架,用於一切繪圖操作,UIKit就是基於Core Graphic實現的,因此它可以實現比UIKit更底層的功能。

Core Graphic

Core Graphic使用Quartz2D作為繪圖引擎,因此Quartz2D其實是Core Graphic的一部分,這兩個名詞密不可分。

2、圖形上下文

畫畫需要畫布,Core Graphics工作是的“畫布”就是圖形上下文,它決定圖形繪制成什麼樣子,並繪制到哪裡去。在“畫布”中,每個連續的繪制操作都可以看成添加一個“圖層”到畫布上,在運行中我們可以通過額外的繪制操作來疊加更多“圖層”來形成復雜的圖形。

推薦使用UIView自動為我們准備好的圖形上下文,因為自定義上下文會降低內存的使用效率,導致性能下降。當需要我們調用UIGraphicsGetCurrentContext()來獲取圖形上下文。

3、路徑

相信很多人都臨摹過書法,在一張薄薄的紙上照著書法家的筆跡來書寫,這個“筆跡”就可以看成路徑,通過確定的路徑,可以確定繪圖的形狀、渲染的區域等等。

通過創建路徑並加入到上下文中渲染就能繪制出想要的圖形。

創建路徑有以下三種方式:

1.使用CGContextRef創建,如CGContextAddArc

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

CGContextBeginPath //開始畫路徑
   CGContextMoveToPoint //移動到某一點
   CGContexAddLineToPoint //畫直線
   CGContexAddCurveToPoint //畫餅圖
   CGContexAddEllipseInRect //畫橢圓
   CGContexAddArc //畫圓
   CGContexAddRect //畫方框
   CGContexClosePath //封閉當前路徑

2.使用CGPathRef創建,如CGPathAddArc

使用方法一繪制路徑後將清空圖形上下文,如果我們想保存路徑來復用,可以使用Quartz提供的CGPath函數集合來創建可復用的路徑對象。

常用的函數如下:

CGPathCreateMutable
   CGPathMoveToPoint
   CGPathAddLineToPoint
   CGPathAddCurveToPoint
   CGPathAddEllipseInRect
   CGPathAddArc
   CGPathAddRect
   CGPathCloseSubpath

這些函數和上面方法一的一一對應,可代替之使用。

CGContextAddPath:添加一個新的路徑

3.使用UIBezierPath創建,如bezierPathWithOvalInRect

UIBezierPath存在於UIKit中,是對路徑繪制的封裝,和CGContextRef類似,優點是更面向對象,我們可以像操作普通對象一樣對其進行操作。

在自定義View的時候,一般使用UIBezierPath來創建路徑就能基本滿足我們的需求,推薦使用。

UIBezierPath的常用方法如下:

@property(nonatomic) CGFloat lineWidth; //線的寬度
@property(nonatomic) CGLineCap lineCapStyle; //起點和終點樣式
@property(nonatomic) CGLineJoin lineJoinStyle; //轉角樣式
//創建path
+ (instancetype)bezierPath;
//矩形
+ (instancetype)bezierPathWithRect:(CGRect)rect;
//以矩形框為切線畫圓
+ (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;
//移動到某一點
- (void)moveToPoint:(CGPoint)point;
//添加直線
- (void)addLineToPoint:(CGPoint)point;
//帶一個基准點的曲線
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
//帶兩個基准點的曲線
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
//封閉路徑
- (void)closePath;
//添加新的路徑
- (void)appendPath:(UIBezierPath *)bezierPath;
//渲染
- (void)fill;
- (void)stroke;

4、渲染

繪畫的最後一步,它之於繪圖的意義如畫畫的最後上顏料一樣。

渲染分為兩種方式:

1)填充Fill:將路徑內部填充渲染

2)描邊Stroke:不填充,只對路徑進行渲染

5、繪圖狀態棧

圖形上下文包含一個繪圖狀態棧,默認為空。

1)保存圖形狀態時,將創建當前圖形狀態的一個副本並入棧。

2)還原圖形狀態時,將棧頂的圖形狀態推出棧並替換當前圖形狀態。

使用:調用CGContextSaveGState來保存,CGContextRestoreGState來還原。

繪圖的核心步驟

在view上繪制一個圖形的方式有很多種,表現形式可能不一樣,但其實質步驟都是一樣的:

1)獲取上下文

2)繪制路徑

3)添加路徑到上下文

4)修改圖形狀態參數

5)渲染上下文

下面我們以畫一個圓形來演示其實現步驟:

1)使用CGContextRef創建路徑

 //獲取上下文
 CGContextRef ctx = UIGraphicsGetCurrentContext();
 //繪制路徑: 圓形(中心坐標200、200、半徑100、起點弧度0、終點弧度2PI、畫的方向0逆1正)
 CGContextAddArc(ctx, 200, 200, 100, 0, M_PI * 2, 0);
 //修改圖形狀態參數
 CGContextSetRGBStrokeColor(ctx, 0.5, 0.5, 0.9, 1.0);//筆顏色
 CGContextSetLineWidth(ctx, 10);//線條寬度
 //渲染上下文
 CGContextStrokePath(ctx);

2)使用CGPathRef創建路徑

 //獲取上下文
 CGContextRef ctx = UIGraphicsGetCurrentContext();
 //創建可變路徑
 CGMutablePathRef path = CGPathCreateMutable();
 //添加圓形到路徑中(所在路徑、不進行變換操作、中心坐標200、200、起點弧度0、終點弧度2PI、畫的方向0逆1正)
 CGPathAddArc(path, NULL, 200, 200, 100, 0, M_PI * 2, 1);
 //將路徑添加到上下文
 CGContextAddPath(ctx, path);
 //修改圖形狀態參數
 CGContextSetRGBStrokeColor(ctx, 0.5, 0.5, 0.9, 1.0);//筆顏色
 CGContextSetLineWidth(ctx, 10);//線條寬度
 //渲染上下文
 CGContextStrokePath(ctx);

3)使用UIBezierPath創建路徑

 //創建路徑
 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];

以上三種方式都可以實現繪制,通過比較我們可以發現使用UIBezierPath創建路徑的形式是最簡潔且最直觀的,推薦使用UIBezierPath,在以後的動畫中我們也將更多地應用UIBezierPath到動畫的實現中。

自定義view的步驟

只需簡單兩步即可:

步驟一:新建一個類,繼承UIView類。

步驟二:重載drawRect方法,在這個方法中進行繪圖。

  

以自定義一個圓形View為例:

1)新建CircleView類,繼承UIView類

CircleView.png

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

  - (void)drawRect:(CGRect)rect {
  }

3)畫一個圓

  - (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)創建CircleView的實例添加到視圖中

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

5)效果圖

效果圖.png

成功畫了一個圓形,現在只差怎樣讓它“動起來”了!

思考

1、Quartz2D的坐標系和UIView的坐標系有什麼不同?

2、繪制圖形時不同路徑使用不同的狀態參數渲染需要怎樣操作?

3、怎樣使用CALayer來自定義View?


文/明仔Su(簡書作者)

原文鏈接:http://www.jianshu.com/p/9ac974756f77

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved