PaintCode 教程1:動態繪製按鈕


PaintCode
 是一個可以讓你像Photoshop同樣去設計你的用戶界面的軟件 – 可是它並非僅僅保存一張圖片看成資源讓你來使用,它可以爲你生成 CoreGraphic 源碼直接使用到View的繪製中.
能夠簡單地說,咱們看重的是下面幾點: ios

  • 節省了開發時間。 若是一行一行的去寫 Core Graphics 代碼,絕對會比用 PaintCode多不少時間。 而時間就是金錢!
  • 減小了程序包大小。 用代碼去繪製各類view,可讓你再也不去添加圖片資源,減小了資源包大小。
  • 讓它能作更動態的改變。. 最後,咱們能夠作更多相比於使用圖片作不到的事情,好比:能夠在程序運行時輕鬆的改變控件的顏色。

深刻: 這篇教程實際基於咱們收到的一些 PaintCode 的使用反饋來寫的。 可是, 教程裏的的全部意見和建議絕對沒有一點瞎掰,絕對原創。
想要儘量的利用學習這篇教程,你們至少知道一點iOS開發。 而且,懂一些 Core Graphics知識會更好(不是100%要求)。 若是你們歷來沒據說過 Core Graphics,真心推薦去看看 Core Graphics系列教程 
廢話很少說,切入正題吧! spring

準備開始

PaintCodeIcon.175x175-75要學習這一系列的PaintCode 教程, 首先咱們須要有個 PaintCode 軟件。你們能夠在這裏下載 試用版, 或者從 Mac App Store購買完整版。 canvas

儘管這個app仍是算比較貴的,可是就我看來,他在生產中的能發揮的價值徹底能物超所值。 若是你們還不肯定, 下載一個試用版在這個教程裏試試吧! 數組


建立第一個動態按鈕

在敲任何代碼以前,咱們將會使用 PaintCode 來設計一個全新的按鈕。
打開 PaintCode,選擇 FileSave,而後把這個項目命名爲 DynamicButton.。這樣的話咱們就能夠在進行這個教程的時候時時的保存了。
點擊屏幕右下的Canvas 按鈕, 而後把畫布大小設置爲寬 480 高 150 pixels,以下圖所示:
PaintCode canvas size in new document
而後經過設置 Underlay color 的RGB值爲 50 50 50來吧畫布的顏色改成淺灰色,以下:
Canvas color in PaintCode xcode

注意: 咱們默認是在非高清畫布上工做,若是你們想看高清的效果,點擊Canvas按鈕邊上的 Retina按鈕。這個按鈕可讓你在高清和非高清之間切換。 app

如今選中工具欄裏的Round Rect 按鈕,而後在畫布裏拖出一個方形來。
咱們能看到,當咱們在畫布裏選中一個形狀的時候,左邊會出現這個形狀的全部屬性。確保選中了剛纔的這個方形,而後把它的屬性修改成以下: 編輯器

  • X: 4
  • Y: 4
  • Width: 473
  • Height: 41

draw a rectangle in PaintCode
接下來,爲了改變按鈕的顏色,咱們須要設置它的Fill值。
在左邊的屬性欄裏, 點擊 Fill,,在彈出的選項裏選擇 Add New Gradient,而後命名爲 ButtonGradient。如今, 點擊 左下的 color stop。 這些在顏色區域底部圓形的顏色選取點是用來給漸變提供所需參數的。
接着,選着右下方的調色盤,而後RGB輸入255 0 0,以下所示:
Setting the button gradient colors
再次點擊調色盤按鈕來關掉它。
如今, 用一樣的辦法把右邊的顏色選取點的 RGB 改成 112 1 0 ,以下:
Setting the button gradient colors
PaintCode 讓你可以去給每一個使用在形狀上的顏色命名,由於它們以一樣的名字出如今代碼裏。 若是界面下方沒有代碼窗口,選擇 View > Code 來打開它。 下面圖片裏高亮的那兩行應該就是剛纔咱們建立的2個顏色。
Color variable in PaintCode Code view
爲了更好的找到這些顏色,咱們最好給他們一個描述性較高的名字。
選中 Colors 選擇欄,在左邊欄下面找到並雙擊 Fill Color。在彈窗裏把它的名字改成 ButtonColorDark,以下所示:
rename color in PaintCode
同理把Stroke Color 名字改成 ButtonColorLight。
如今回到位於中間的形狀屬性欄,選擇 Stroke 下來框裏的 System Colors > Common Colors > BlackColor,以下圖所示,把描邊顏色改成黑色。
add a stroke color in PaintCode
Increase the Width parameter to 2 under the Stroke sub-section, as so:
stroke width in PaintCode
如今,咱們要給按鈕加一個爲發光 ,選擇 Add New Shadow… 在Fill的下拉框裏選擇 Outer Shadow,以下所示:
Add new shadow in PaintCode
像上面的按鈕同樣給這個陰影一個好的名字,把它名字改成 OuterGlow。 接下來, 選中 Color邊上的下拉框,而後在顏色選取框裏選着白色框, 打開邊上的那個顏色調整按鈕
把陰影偏移和陰影大小調整爲下圖同樣:
Adding a glow in PaintCode
切換到 Colors 選項卡下面而後把 Glow 改成 InnerGlowColor。
接着,在Add New Shadow的下拉框裏面給 Inner Shadow 加一個內高光。把這個高光命名爲Highlight, 顏色設置爲 白色,透明度爲 130, 而後把offsets 和 blur radius設置爲以下所示:

根據前面的教程。這個顏色的名字可能已是默認的 Shadow Color 2 ,若是不同,就把它改爲這個名字。
如今,咱們的按鈕應該和下面同樣了:
Final Button
到這個時候,咱們的按鈕已經看起來挺不錯的了,可是他的大小是定死了的。要讓它能夠隨意的改變大小,咱們須要給他加一個frame。 咱們會在代碼裏改變它的大小,接下來咱們會在PaintCode裏面設置frame,這樣可讓裏面的全部東西都是可變大小的。 ide

給按鈕加Frame

在頂部工具欄裏選擇 Frame ,而後畫一個框包住按鈕。把這個frame的屬性設置爲以下:
Adding a frame for the button
同時選中Frame 和 Rounded Rectangle, 按下 Option-Command-G 組合鍵來把它們放在一個group裏。 或者, 咱們能夠選擇去按菜單裏的 Selection > Group來達到一樣的效果。 最後吧這個group米命名爲Button。
咱們如今能夠看到在左邊的邊欄最頂上,可能看到button group 和它包括2個元素,以下所示:
Grouping elements
在左邊面板裏選中 Rounded Rectangle。 找到設置這個形狀大小限定的區域 – 它是在座標設置左邊的一個方框, 裏面包含了幾個桿狀,彈簧狀的橫條。
ResizeWindow
咱們如今須要這個按鈕可以水平的豎直的去改變大小,同時又能保持水平中心不變。 因此咱們就要吧外部的約束設置爲直的(固定了大小), 而後底部應該設置爲彈簧條(可以隨意的改變大小)。 這樣就能讓按鈕保持在水平中心對齊了。
可是,爲了能讓按鈕能隨意的改變大小和frame同樣,咱們須要吧方框裏面的杆都改爲彈簧。
咱們僅僅須要點一下這些杆,就可讓他們在直杆和彈簧之間切換。
當你們完成了修改約束,樣子應該以下所示:
Button constraints
到這裏,已經完成了大部分工做了! 如今咱們選中按鈕邊上的 Frame,而後隨便把這個按鈕左右上下拖動試試,它的樣子大概以下圖:
Final button
如今PaintCode裏的畫圖這部分的工做已經完成 —咱們接下來要開始把它加入xcode裏了。 工具

加入iOS項目裏

在完成了咱們項目所用到的按鈕之後— 固然,咱們沒有寫一行代碼!別急,如今捲起袖口準備開始擼代碼吧!
我已經爲你們準備了一個用開測試這個按鈕的起始項目。下載這個起始項目, 解壓,而後在xcode裏打開。看看裏面有什麼吧。 學習

注意: 這個項目裏的storyboard是關掉了Autolayout的。並非每一個項目都須要這樣,可是在這裏,咱們更偏向於使用springs和struts約束。

這是一個Tabbar 應用,裏面包含了3個view controller,他們分別是爲這個系列教程每次建立的控件準備的。 在此次的 PaintCode 教程裏,咱們將會使用 ButtonViewController 來展現咱們的按鈕。
在 Classes > Views下面有一個空文件夾。此次, 咱們在這裏面建立本身的類。咱們會繼承一個現有的控件,而後去改變他的繪製代碼,而不是徹底的用一個空UIView來實現。
而在這個教程裏,咱們繼承UIButton。讓咱們開始吧!

建立按鈕

在 Classes 組下面, 右鍵 Views 組。選擇 NewFile… 而後建立一個 iOSCocoa TouchObjective-C class模板,把這個類命名爲 ButtonView,而後繼承自 UIButton。
這個類將會使用咱們在 PaintCode裏建立的繪製代碼。
如今咱們作一些準備工做, 打開 ButtonView.m,刪除 initWithFrame: 方法,而後反註釋 drawRect:。以下所示:

[objc]  view plain copy
  1. #import "ButtonView.h"  
  2. @implementation ButtonView  
  3. - (void)drawRect:(CGRect)rect  
  4. {  
  5.     // Drawing code  
  6. }  
  7. @end   

drawRect: 這裏就是咱們施展魔法的地方 – 這裏咱們會把PaintCode生成的代碼加上。 若是你不熟悉 drawRect:甚至不知道它是作什麼的,最好先去看看咱們的 Core Graphics 系列教程吧。
回到 PaintCode 而後找到 Code View。若是沒有找到, 選擇 View > Code 來打開這個面板。找到代碼生成配置模塊:
PaintCode code settings
把平臺設置爲 iOS > Objective-C,系統版本設置爲 iOS 5+, 默認原點爲Default Origin,內存管理爲 ARC。若是這是你第一次使用 PaintCode — 或者你歷來沒弄過這些東西 — PaintCode已經幫你作了無缺的內存管理了。
複製而且把這些代碼從 PaintCode裏粘貼到 drawRect:裏面。這個方法應該和下圖同樣了:

[objc]  view plain copy
  1. - (void)drawRect:(CGRect)rect  
  2. {  
  3.     //// General Declarations  
  4.     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();  
  5.     CGContextRef context = UIGraphicsGetCurrentContext();  
  6.    
  7.     //// Color Declarations  
  8.     UIColor* buttonColorDark = [UIColor colorWithRed0.439 green0.004 blue0 alpha: 1];  
  9.     UIColor* buttonColorLight = [UIColor colorWithRed1 green0 blue0 alpha: 1];  
  10.     UIColor* innerGlowColor = [UIColor colorWithRed1 green1 blue1 alpha0.502];  
  11.     UIColor* shadowColor2 = [UIColor colorWithRed1 green1 blue1 alpha0.51];  
  12.    
  13.     //// Gradient Declarations  
  14.     NSArray* buttonGradientColors = [NSArray arrayWithObjects:  
  15.                                      (id)buttonColorLight.CGColor,  
  16.                                      (id)buttonColorDark.CGColor, nil nil];  
  17.     CGFloat buttonGradientLocations[] = {01};  
  18.     CGGradientRef buttonGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)buttonGradientColors, buttonGradientLocations);  
  19.    
  20.     //// Shadow Declarations  
  21.     UIColor* outerGlow = innerGlowColor;  
  22.     CGSize outerGlowOffset = CGSizeMake(0.1, -0.1);  
  23.     CGFloat outerGlowBlurRadius = 3;  
  24.     UIColor* highlight = shadowColor2;  
  25.     CGSize highlightOffset = CGSizeMake(0.12.1);  
  26.     CGFloat highlightBlurRadius = 2;  
  27.    
  28.     //// Frames  
  29.     CGRect frame = CGRectMake(0048049);  
  30.    
  31.     //// Button  
  32.     {  
  33.         //// Rounded Rectangle Drawing  
  34.         CGRect roundedRectangleRect = CGRectMake(CGRectGetMinX(frame) + 4, CGRectGetMinY(frame) + 4, CGRectGetWidth(frame) - 741);  
  35.         UIBezierPath* roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect: roundedRectangleRect cornerRadius: 6];  
  36.         CGContextSaveGState(context);  
  37.         CGContextSetShadowWithColor(context, outerGlowOffset, outerGlowBlurRadius, outerGlow.CGColor);  
  38.         CGContextBeginTransparencyLayer(context, NULL);  
  39.         [roundedRectanglePath addClip];  
  40.         CGContextDrawLinearGradient(context, buttonGradient,  
  41.                                     CGPointMake(CGRectGetMidX(roundedRectangleRect), CGRectGetMinY(roundedRectangleRect)),  
  42.                                     CGPointMake(CGRectGetMidX(roundedRectangleRect), CGRectGetMaxY(roundedRectangleRect)),  
  43.                                     0);  
  44.         CGContextEndTransparencyLayer(context);  
  45.    
  46.         ////// Rounded Rectangle Inner Shadow  
  47.         CGRect roundedRectangleBorderRect = CGRectInset([roundedRectanglePath bounds], -highlightBlurRadius, -highlightBlurRadius);  
  48.         roundedRectangleBorderRect = CGRectOffset(roundedRectangleBorderRect, -highlightOffset.width, -highlightOffset.height);  
  49.         roundedRectangleBorderRect = CGRectInset(CGRectUnion(roundedRectangleBorderRect, [roundedRectanglePath bounds]), -1, -1);  
  50.    
  51.         UIBezierPath* roundedRectangleNegativePath = [UIBezierPath bezierPathWithRect: roundedRectangleBorderRect];  
  52.         [roundedRectangleNegativePath appendPath: roundedRectanglePath];  
  53.         roundedRectangleNegativePath.usesEvenOddFillRule = YES;  
  54.    
  55.         CGContextSaveGState(context);  
  56.         {  
  57.             CGFloat xOffset = highlightOffset.width + round(roundedRectangleBorderRect.size.width);  
  58.             CGFloat yOffset = highlightOffset.height;  
  59.             CGContextSetShadowWithColor(context,  
  60.                                         CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)),  
  61.                                         highlightBlurRadius,  
  62.                                         highlight.CGColor);  
  63.    
  64.             [roundedRectanglePath addClip];  
  65.             CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(roundedRectangleBorderRect.size.width), 0);  
  66.             [roundedRectangleNegativePath applyTransform: transform];  
  67.             [[UIColor grayColor] setFill];  
  68.             [roundedRectangleNegativePath fill];  
  69.         }  
  70.         CGContextRestoreGState(context);  
  71.    
  72.         CGContextRestoreGState(context);  
  73.    
  74.         [[UIColor blackColor] setStroke];  
  75.         roundedRectanglePath.lineWidth = 2;  
  76.         [roundedRectanglePath stroke];  
  77.     }  
  78.    
  79.     //// Cleanup  
  80.     CGGradientRelease(buttonGradient);  
  81.     CGColorSpaceRelease(colorSpace);      
  82. }  

若是你們仔細的瀏覽了代碼,會發現它是用Core Graphics來繪製的。 或多或少的方法你們可能都沒見過,可是它們並不難於去理解。 而且,這也是咱們使用 PaintCode 的緣由之一;爲了省掉學習 Core Graphics而且花更少的時間去在那裏慢慢的調試繪製代碼! :]

注意: 你們暫時不用去太擔憂 drawRect: 裏面代碼的縮進和語法。咱們等會兒會再回來,而且作一些修改 ,包括把語法改成 moden Objective-C。

如今該來測試咱們的按鈕了。
在 Project Navigator 找到咱們的storyboard 而後選中 ButtonViewController。在Object Library裏拖出來一個View 而後把它的 X 和 Y座標爲 20, 35。而後, 把它的 Width 和 Height 設置爲 280,41。
最後, 把它的 Autosizing 設置 修改成只能水平擴張,以下所示:
Button view autosizing
切換到Identity Inspector 而後把它的類名設置爲 ButtonView。

注意:你們可能有疑問爲何在storyboard裏面是一個 UIView , 可是 ButtonView又繼承與UIButton。 緣由很簡單 UIButton 它繼承於 UIView所以一個按鈕任然是一個 view。

在此次 PaintCode 教程的後部分 ,咱們會讓它和真正的按鈕同樣起做用。畢竟 —他繼承了UIButton。

Subclass watch out
是時候檢測咱們漂亮的新按鈕了!
點擊 Run 看看咱們的按鈕什麼樣的吧:
First button test
額…按鈕貌似被砍掉了一塊,怎麼回事兒?
如今找到ButtonView.m裏的 drawRect::

[objc]  view plain copy
  1. - (void)drawRect:(CGRect)rect  
  2. {  
  3.     ...  
  4.     //// Frames  
  5.     CGRect frame = CGRectMake(0048049);  
  6.    
  7.     ...  
  8. }  

原來!!!!這個按鈕的frame是定死了的。咱們想要的是一個能夠動態改變大小的按鈕 — 而且可以適應咱們給它設置的大小。
這個問題很簡單,修改設置 frame的那行代碼爲以下:

[objc]  view plain copy
  1. - (void)drawRect:(CGRect)rect  
  2. {  
  3.     ...  
  4.     //// Frames  
  5.     CGRect frame = rect;  
  6.    
  7.     ...  
  8. }  

上面那段代碼是把view的frame設置爲繪製的frame的大小。
點擊Run,讓咱們再來一發!
First button test fixed
耶!按鈕的繪製終於和咱們想要的同樣了。旋轉模擬器(或者設備) 咱們會看到按鈕和咱們指望的同樣保持水平位置,改變着寬。
咱們已經完成了大部分了 — 可是咱們怎讓才能讓它變得更動態呢?

動態的設置按鈕屬性

動態的控制按鈕大小是挺不錯的 —可是如今,咱們要作一件更神奇的事情;在 ButtonViewController 裏面加一些滑動條來控制按鈕的RGB值。
回到storyboard,拖3個Slider 而且把它們放在按鈕下面。 在 Size Inspector裏面, 把3個slider的 Autosizingwidget 設置爲以下所示:
Slider Autosizing
你們還能夠把按鈕往下移一點,而後放一個label 寫着 「Tap Me」,這樣的話可讓你的用戶知道按鈕是能夠點擊的。Storyboard應該以下圖同樣的:
Scene with sliders
找到Attributes Inspector,把slider的 Min Track Tint 的顏色設置爲以下的RGB值:

  • Top slider: R:255 G:0 B:0
  • Middle slider: R:0 G:255 B:0
  • Bottom slider: R:0 G:0 B:255

咱們的slider應該和下面的差很少了:
Slider colors

注意: 有的時候slider的背景色也會隨着Min Tint color 的改變而改變。這是一個xcode的bug,咱們能夠直接吧slider的背景色設置爲默認的。

而後找到 ButtonViewController.m,在頂部加入下面的代碼:

[objc]  view plain copy
  1. #import "ButtonView.h"  
  2. @interface  ButtonViewController ()  
  3. @property (weak, nonatomic) IBOutlet UISlider *blueSlider;  
  4. @property (weak, nonatomic) IBOutlet ButtonView *buttonView;  
  5. @property (weak, nonatomic) IBOutlet UISlider *greenSlider;  
  6. @property (weak, nonatomic) IBOutlet UISlider *redSlider;  
  7. @end  

把 buttonView 鏈接到咱們設置的那個 UIView 上,而後把3個 UISlider 和storyboard裏面各自對應的鏈接上。若是你們還不知道怎麼鏈接view和outlet,能夠去看看咱們的 How To Create a Simple iPhone App 系列教程。
爲了能讓按鈕的顏色隨着slider的拖動而改變, 咱們的 ButtonView 須要隨着slider 去更新。
找到 ButtonView.h 而後把下面3行加入 @interface 和 @end 之間:

[objc]  view plain copy
  1. @property (assign, nonatomic) CGFloat blueColor;  
  2. @property (assign, nonatomic) CGFloat greenColor;  
  3. @property (assign, nonatomic) CGFloat redColor;  

這些是儲存按鈕RGB值的變量。
而後切換到 ButtonView.m ,找到 drawRect:。咱們會注意到這段 Gradient Declarations 用的是舊的NSArray代碼。爲了保持良好的代碼風格,把 Gradient Declarations 那行替換成以下:

[objc]  view plain copy
  1. NSArray *buttonGradientColors = @[(id)buttonColorLight.CGColor, (id)buttonColorDark.CGColor];  

而後,把全部帶 「Color Declarations」 註釋的代碼替換成以下:

[objc]  view plain copy
  1. -(void)drawRect:(CGRect)rect {  
  2.     ...  
  3.     // 1  
  4.     UIColor *buttonColorLight = [UIColor colorWithRed:self.redColor green:self.greenColor blue:self.blueColor alpha: 1];  
  5.    
  6.     // 2  
  7.     if (self.state == UIControlStateHighlighted) {  
  8.         buttonColorLight = [UIColor colorWithRed:self.redColor green:self.greenColor blue:self.blueColor alpha:0.5];  
  9.     }  
  10.    
  11.     // 3  
  12.     CGFloat buttonColorLightRGBA[4];  
  13.     [buttonColorLight getRed:&buttonColorLightRGBA[0]  
  14.                        green:&buttonColorLightRGBA[1]  
  15.                         blue:&buttonColorLightRGBA[2]  
  16.                        alpha:&buttonColorLightRGBA[3]];  
  17.    
  18.     // 4  
  19.     UIColor *buttonColorDark = [UIColor colorWithRed:(buttonColorLightRGBA[0] * 0.5)  
  20.                                                green:(buttonColorLightRGBA[1] * 0.5)  
  21.                                                 blue:(buttonColorLightRGBA[2] * 0.5)  
  22.                                                alpha:(buttonColorLightRGBA[3] * 0.5 + 0.5)];  
  23.     // 5  
  24.     UIColor *innerGlowColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.53];  
  25.     UIColor *shadowColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.51];  
  26.    
  27.     ...  
  28. }  

咱們在這裏具體作了:

  1. 申明一個局部 UIColor 變量做爲按鈕的淺色 (記住,咱們在漸變編輯器裏設置的那個),可是如今咱們使用的是來自slider的RGB值。
  2. 若是用戶安下了按鈕,把按鈕的顏色的alpha下降50%, 這時候按鈕的狀態是 UIControlStateHighlighted。這能在按下按鈕時提供用戶一些視覺上的反饋。
  3. 把按鈕的rgb值儲存到一個CGFloat的數組裏。
  4. 基於淺色建立按鈕的深色 (記住,咱們在漸變編輯器裏設置的那個) 。
  5. 基於一些固定值建立內發光和陰影。

在這裏咱們最好給按鈕一個初始顏色。 由於咱們用的是Storyboard,因此咱們須要重載 initWithCoder: (在ButtonView.m) 來實現:

[objc]  view plain copy
  1. -(id)initWithCoder:(NSCoder *)coder {  
  2.     if (self = [super initWithCoder:coder]) {  
  3.         self.redColor = 1.0f;  
  4.         self.greenColor = 0.0f;  
  5.         self.blueColor = 0.0f;  
  6.         self.contentMode = UIViewContentModeRedraw;  
  7.     }  
  8.    
  9.     return self;  
  10. }  

這個設置把view的內容模式設置爲了 UIViewContentModeRedraw,而且讓按鈕初始的時候是紅色的。

注意: 若是你們好奇爲何重載 initWithCoder: 而不是 initWithFrame:, 這是由於initWithFrame:是用來在代碼裏手動生成view的, 然而 initWithCoder: 是用來初始化一個從Nib或者Storyboard裏面生成的view的。

在咱們開始測試以前,還有最後一件事作。找到 ButtonViewController.m 而後吧 viewDidLoad 替換成以下:

[objc]  view plain copy
  1. -(void)viewDidLoad {  
  2.     [super viewDidLoad];  
  3.    
  4.     [self.redSlider setValue:self.buttonView.redColor];  
  5.     [self.greenSlider setValue:self.buttonView.greenColor];  
  6.     [self.blueSlider setValue:self.buttonView.blueColor];  
  7. }  

上面的代碼把每一個slider的顏色設置爲按鈕各個RGB通道的值。
編譯運行, 試試滑動這些slider,以下所示:
Testing the sliders
等下!!爲何沒有反應!
咱們確實鏈接了slider, 可是如今在 ButtonViewController 沒有任何方法去響應slider值的改變。咱們須要加一些 IBAction 代碼來處理這些值。

響應事件

響應按鈕和slider的事件其實很簡單。
ButtonViewController.m里加入以下代碼:

[objc]  view plain copy
  1. -(IBAction)sliderValueChanged:(UISlider *)slider {  
  2.     if (slider == self.redSlider) {  
  3.         self.buttonView.redColor = self.redSlider.value;  
  4.     } else if (slider == self.greenSlider) {  
  5.         self.buttonView.greenColor = self.greenSlider.value;  
  6.     } else if (slider == self.blueSlider) {  
  7.         self.buttonView.blueColor = self.blueSlider.value;  
  8.     }  
  9.    
  10.     [self.buttonView setNeedsDisplay];  
  11. }  

上面的能收到一個值改變了的slider的指針。 咱們經過和屬性裏聲明的slider比較來肯定具體修改哪一個slider的值。
咱們能夠注意到,在代碼的最後咱們調用了setNeedsDisplay 來讓按鈕可以更新到最新的顏色。
如今回到Storyboard, 依次把slider的 Value Changed event 和ButtonViewController裏的 sliderValueChanged: 鏈接起來,以下所示:
Connecting the sliders
Build and run your project again, and try once more to move the sliders around to change the button’s color, as below:
Working sliders
叼炫酷!如今咱們的按鈕,不經能任意改變大小!還能隨便的改變顏色了!
如今咱們來試試按鈕按下有啥反應。
額~~~ 啥都沒發生! 按鈕並無高亮來表示按下,也沒有任何提示你的信用卡剛被劃掉了99.99$. (開個玩笑! :])
咱們尚未給按鈕鏈接事件 — 接下來咱們就開始吧!

最後的點擊

回到 ButtonView.m 而後加入下面的方法:

[objc]  view plain copy
  1. -(void)setEnabled:(BOOL)enabled {  
  2.     [super setEnabled:enabled];  
  3.     [self setNeedsDisplay];  
  4. }  
  5. -(void)setHighlighted:(BOOL)value {  
  6.     [super setHighlighted:value];  
  7.     [self setNeedsDisplay];  
  8. }  
  9. -(void)setSelected:(BOOL)value {  
  10.     [super setSelected:value];  
  11.     [self setNeedsDisplay];  
  12. }  

上面的代碼是讓按鈕在 enabled 和 disabled,selected 和 unselected,highlighted 或者 unhighlighted 的時候可以從新繪製一次。 這是爲了讓咱們能看到具體的改變,當咱們按下按鈕時候。
接着,把下面的代碼加進ButtonViewController.m:

[objc]  view plain copy
  1. -(IBAction)buttonTapped:(UIButton *)button {  
  2.     ButtonView *buttonView = (ButtonView *)button;  
  3.    
  4.     NSString *messageString = [NSString stringWithFormat:@"Red: %fnGreen: %fnBlue: %fn Alpha: %f",  
  5.                                buttonView.redColor,  
  6.                                buttonView.greenColor,  
  7.                                buttonView.blueColor,  
  8.                                buttonView.alpha];  
  9.    
  10.     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Button Colors"  
  11.                                                         message:messageString  
  12.                                                        delegate:nil  
  13.                                               cancelButtonTitle:@"Dismiss"  
  14.                                               otherButtonTitles:nil];  
  15.     [alertView show];  
  16. }  

這個方法的做用是在按鈕按下之後,彈出一個提醒框,顯示當前的RGB和Alpha值。
在Storyboard裏,把 Touch Up Inside 和這個方法聯繫在一塊兒。
最後在運行一次程序,按下按鈕看看結果吧! 應該出現和下面同樣的畫面:
Final project
太棒了! -一切都正常工做。

何去何從?

你們能夠在這裏下載所需的PaintCode文件,和相關的Xcode項目。
恭喜你們如今已經掌握了大部分的PaintCode功能了。它能極大的縮短設計app調試UI的時間。
這個系列教程還剩下2部分;第二部分是教你們如何去建立一個自定義進度條,第三部分是使用貝塞爾曲線繪製箭頭。
如今,咱們還能夠再給這個項目增長一下功能讓錦上添花:

  • 本身慢慢的熟悉 PaintCode 的其餘功能和特性。
  • 增長字符串,陰影,以及更多的其餘特效。
  • 重寫ButtonView裏的 initWithFrame: ,這樣能讓你使用代碼生成動態按鈕。
  • 給 ButtonView 建立本身的初始化方法,讓咱們能初始按鈕的顏色參數。

但願你們能喜歡這個 PaintCode 教程,而且但願你們能繼續關注咱們接下來的2部。接下來的加成將會愈來愈深刻,而且會有一點的難度 — 可是我知道這對你們來講是小菜一碟。


http://www.raywenderlich.com/36341/paintcode-tutorial-dynamic-buttons

相關文章
相關標籤/搜索