View Hierarchy
view可以有subviews,最後組成一個hierarchy,最上層是UIWindow,通常不會碰到它。而ViewController有一個property "view",這就指向了這個hierarchy的最上層view (但是不是UIWindow? 不確定)。interface builder會把storyboard存成xml,所以要programmatically create一個view,必須要用:
CGFloat
跟UIView drawing有關的float / double 都應該要用CGFloat 當作UIView座標系統內的單位。UIView 座標系統
很瞎的是,原點在螢幕左上角,往右增加x,往下增加y。point: 座標系統內的個體點,是座標系統內的最小單位,這是一個抽象的單位。
pixel:螢幕上實體能產生一個顏色的最小單位,是實體單位,有可能多個pixel組成一個point,也有可能是1對1的關係。
Bounds (CGRect)
UIView在自己的view coordinate system中所佔(畫出)的points範圍。center and frame
容易混淆的是,UIView的這兩個屬性事實上是說在superview coordinate system中的位置與大小。由於有可能在superview中被rotate或是scale,所以UIView的frame != UIView的bounds,這個要注意:如何畫出一個UIVIew?
override UIView的draw function,系統要填滿UIView所佔的bounds中某個CGRect (小於等於bounds) 的時候,他就會來呼叫這個draw function。這是系統callback,我們不能呼叫,如果要redraw,就要利用setNeedsDisplay()
1. 繪製UIView時,我們需要一個context,這定義了畫在哪個buffer (有可能是screen / printing / off-screen等),在draw(CGrect) callback中 利用 UIGraphicsGetCurrentContext function 獲得。
2. 創建paths
3. 設定paths 屬性
4. fill or stroke
畫出Text
通常我們用UILabel,但客製化一個view的時候,可能需要製作自己的text,可以用以下的code:NSAttributedString 不是 NSString,總之是給custom draw用的,不過這邊有一些眉角,看起來似乎很煩,用到再說吧。
畫出image
通常我們也是用UIImageView,但是要自己畫的時候就使用UIImage。當UIView bounds改變的話?
UIView bounds改變的時候,系統預設不會去呼叫draw function,而是會根據此UIView 的 contentMode:UIViewContentMode 來決定是要scale或是translate,但是這通常會看起來很怪,所以如果要在bounds change的時候自己決定如何重劃的話,就要把contentMode設定成 redraw,如此我們的draw function就又會被系統呼叫。Reset to Suggested Constraints
interface builder可以幫我們自動根據snap to edges (藍色線距離四個邊界的長度)做constraints:可以看到貼近四個edges的constraints已經被設定了:
export UIView 屬性到Interface Builder
利用Xcode preprocessor @IBDesignable, @IBInspectable這一點比Android Studio 酷多了!!!!!!!!!!
沒有留言:
張貼留言