
圖片元件來源:Designing Buttons in iOS 5
Hi, @vince78718 です
最近想在 UIView
中做出像 UIButton
一樣,可以用單一背景指定邊角寬度、拉伸開來成為整個按鈕的背景,原本想說完了,該不會又要手刻 UI library 來達成我的需求。
以前 iOS 比賽的 App 有遇到一樣的情形,最後有點偷懶,在 table view 的每一格 cells 用 CALayer
動態畫背景,下場就是非常非常吃資源,一滑過去一直卡一直卡,幾乎沒有辦法使用。
於是去 Google 一下有沒有解法,想必也有許多人想這樣做,於是就讓我找到了 ~~
UIButton 的做法
首先,根據之前找到的 "DESIGNING BUTTONS IN IOS 5" 這篇文章,除了直接用最簡單的方法,就是用 resizableImageWithCapInsets: 這個 UIImage 的 method 來指定想要使用的邊緣寬度。
另外,在 UIButton 宣告指定 UIButtonType 的時候請注意,在 iOS 7 中,原有的 UIButtonTypeRoundedRect 已經 deprecated ,請使用 UIButtonTypeSystem。通常需要向下支援,判斷裝置版本後再給予相對應的 type 。
本段相關 doc: resizableImageWithCapInsets:, buttonWithType:, UIButtonType
UIView 設定背景第一步
最原始的做法如下,由於 colorWithPatternImage: 的關係,就會發現背景被像棋盤般的排列,根本不是我想要的
本段相關 doc: colorWithPatternImage:
把背景「畫」出來
接下來要準備一個「畫布」,就是 context,將背景的圖片根據設定的邊框寬度,繪製到指定大小(這邊是目標 UIView 的 frame 大小),再將結果轉為 UIImage 、包裝成 UIColor instance ,再指定為 UIView 的背景。
但是 ... 他是模糊的啊!明明有在 project 中有加 @2x 的圖片說 ...


左為模糊、右為清晰的圓角(這邊圓角半徑沒很大,大一點的話差異會更清楚)
本段相關 doc: UIGraphicsBeginImageContext
原因是 Retina !!
如果你不想支援 retina ,可以跳過這段沒關係(誤)。
在 iOS 坐標系統中是用 points 而非 pixels 。在 iOS 4.0 之後,因為 scale factor 的關係,在繪製的時候,非 retina 螢幕為 1.0(pt:px = 1:1) , retina 螢幕則是 2.0(pt:px = 1:2)。而 SDK 也給了方便的做法,當指定為 0.0f 的時候,就會自動使用該裝置的 scale factor。
因此,這裡的做法要稍微改變一下:將設定畫布的 UIGraphicsBeginImageContext 換成 UIGraphicsBeginImageContextWithOptions ,便多了第三個參數可以指定 scale factor。
而第二個參數則是設定 opaque (不透明),如果你的圖片有含有 alpha 層,請設定為 NO ,無則設定為 YES 。
破關

本段相關 doc: scale factor, UIGraphicsBeginImageContextWithOptions
範例 Repo
Github: Page | Downloador clone me

取扱説明書
這個 repo 在主要的步驟有加上 !!! 註解,
可以在下拉的 method 清單看到,讓大家更容易觀看


若是文章、 code 中有錯誤的地方、或是交流討論,歡迎電梯下樓留言指出
謝謝觀看、下次見~!
Reference
- Designing Buttons in iOS 5 | Nathan Barry - http://nathanbarry.com/designing-buttons-ios5/
- How to fill background image of an UIView - http://stackoverflow.com/a/8077854
- UIGraphicsGetImageFromCurrentImageContext() Retina resolution? - http://stackoverflow.com/a/4965155
- How to use UIGraphicsBeginImageContextWithOptions? - http://stackoverflow.com/a/5148042
沒有留言:
張貼留言