[CS193P] 史丹佛大學的iPhone應用開發課程:第五堂課摘要及心得筆記之二

上一次的課程中,我們提到了View的一些實做上的觀念,包含座標系統以及如何建立自己的View。在這次的筆記當中,我們將進一步探討如何使用View來幫助我們繪圖或是產生動畫的效果,趕快來一起學習吧!
評論
評論

上一次的課程中,我們提到了 View 的一些實做上的觀念,包含座標系統以及如何建立自己的 View。在這次的筆記當中,我們將進一步探討如何使用 View 來幫助我們繪圖以及操作圖片,趕快來一起學習吧!

View 繪圖

在上次筆記中的最後一小節中我們曾經談到如何建立自己的 View 類別,而當我們如果想要修改這個 View 的繪圖方式時,我們可以重載 - (void)drawRect:(CGRect)rect 這個方法,如果我們沒有去重載這個方法的話,預設就是會使用 backgroundColor 來填滿整個 View。

然而,什麼時候我們需要在 controller 中呼叫 drawRect 呢?事實上,我們並不需要呼叫這個方法,在 iPhone 上有一個很重要的設計原則就是要盡量讓 Cocoa 去幫我們處理這些瑣事,也同樣能夠增進效能。而當我們真的需要重畫 View 的時候只需要呼叫 - (void)setNeedsDisplay 就可以了。

在 iPhone 的平台上面,我們主要會使用 CoreGraphics 這組繪圖的 API 來進行 View 的繪圖,要注意的是,它是以 C 語言為基礎的函式庫,並非是 Objective-C,而 CG 這套函式庫提供了一些簡單但是好用的功能,包括變形、路徑、顏色、字體及一些繪圖的操作等等。

在我們開始繪製圖形之前,一定要先了解所謂的 Context 的概念,context 在英文裡面可以背翻譯作為上下文或是背景,你可以想像成 context 是一片畫布,而且也存放了一些繪圖中的資訊,像是像在使用的字體大小或是路徑等等。而這些 context 的會在呼叫 drawRect 之前就被設定好,我們只需要呼叫 (CGContextRef)UIGraphicsGetCurrentContext(void); 就可以取得現有的 context,在搭配上 CG 的一些函式,就可以修改 context 的設定值,以便完成我們的繪圖作業。

雖然我們剛剛說 CG 主要是以 C 語言為主的 API,但其實 UIKit 也有將一些 API 包裝成 Obj-C 的格式,像是 UIColor 就可以提供我們快速的設定顏色,而 UIFont 則提供了一個簡單的介面來存取系統的字體。在投影片的第 42 頁中有一些範例可以提供參考。

接下來我們用一段簡單的程式馬來看看實際的運作情形吧!

- (void)drawRect:(CGRect)rect {     CGRect bounds = [self bounds]; // 取得 View 的範圍      [[UIColor grayColor] set]; // 設定顏色為灰色     UIRectFill (bounds); // 將 View 的範圍塗滿灰色      CGRect square = CGRectMake (10, 10, 50, 100); // 建立一個方形     [[UIColor redColor] set]; // 設定顏色為紅色     UIRectFill (square); // 將方形塗滿紅色      [[UIColor blackColor] set]; // 設定顏色為黑色     UIRectFrame (square); // 將方形塗上黑色外框 }
成果如下圖,應該不難理解:
但如果我們需要比較複雜的圖像,一般會透過以下幾個步驟:
  1. 取得 context
  2. 建立路徑
  3. 選擇顏色
  4. 填滿路徑或是畫邊框
  5. 重複以上步驟

而路徑又可以包含直線、邊角、弧線或是四邊型,我們必須先建立好路徑,才能夠繪圖。在投影片的第 47 張中有一些常用的函式可以做參考,我們可以發現,針對 context 和路徑的函式其實相當類似,唯一的不同點是建立好的路徑可以重複使用,而 context 不行。下面是一個用路徑繪圖的範例:

- (void)drawRect:(CGRect)rect {     CGContextRef context = UIGraphicsGetCurrentContext(); // 取得現在的 context     [[UIColor grayColor] set]; // 將顏色設定成灰色     UIRectFill ([self bounds]); // 將現在的 View 填滿灰色      CGContextBeginPath (context); // 開始建立路徑     CGContextMoveToPoint (context, 75, 10); // 先移動到 (75, 10) 這個點     CGContextAddLineToPoint (context, 10, 150); // 從 (75, 10) 畫一條線道 (10, 150),注意,現在的定位點也同時移動到 (10, 150)     CGContextAddLineToPoint (context, 160, 150); // 從 (10, 150) 畫一條線到 (160, 150)     CGContextClosePath (context); // 關閉路徑      [[UIColor redColor] setFill]; // 設定紅色為填滿路徑的顏色     [[UIColor blackColor] setStroke]; // 設定黑色為邊的顏色     CGContextDrawPath (context, kCGPathFillStroke); // 將路徑繪製出來,kCGPathFillStroke 代表要填滿顏色並且塗邊 }

而成果的圖如下,是不是很方便呢?

圖片及文字

UIImage 是用來呈現圖片的 UIKit 類別,我們可以透過下幾種方法建立:

  1. +[UIImage imageNamed:(NSString *)name] -- 讀取程式中的圖片,也就是存放在 Project 的 Resource 的圖片
  2. -[UIImage initWithContentsOfFile:(NSString *)path] -- 讀取檔案系統中的圖片
  3. -[UIImage initWithData:(NSData *)data] -- 讀取記憶體中的圖片

而我們也可以透過剛剛學會的 Core Graphic 函式庫來動態產生圖片,一般的步驟是:

  1. 建立特定大小的 CGGraphicsContext
  2. 繪圖
  3. 將 context 存為圖檔
  4. 清理 context

另外還有兩個很方便的功能:當我們如果有 UIImage 物件時,我們可以透過以下 API 來取得 JPG 或是 PNG 的檔案格式:

  • NSData *UIImagePNGRepresentation (UIImage * image);
  • NSData *UIImageJPGRepresentation (UIImage * image);

而在投影片第 57 頁的地方,也提供了在 UIImage 上繪製 NSString 的 API,大家如果有需要可以參考。

結論

在這次的筆記當中,我們學到了關於 VIew 繪圖的部份。在下一次的筆記當中,將會進入一些 View 的動畫效果,敬請期待!

參考資源