1.View and Window Architecture
1.1 View Architecture Fundamentals
一個view對象負責:繪制+區域內點擊事件+處理subview的坐標繪制。其繪制和動畫時間是結合Core Animation layers來處理。當你需要處理渲染和動畫時,可以直接通過操作layer來完成。這些layer對象背后是Core Animation渲染對象,以及終極的完成屏幕上每一個bit渲染的hardware buffers。
1.1.1 View Hierarchies and Subview management
容器view和內容view ,結合成super--sub的關系,super view維護了一個數組來存儲subviews,后加入的subview顯示在最上端。當subview被設為不透明,其在顯示上遮擋了superview的部分,操作上也遮擋了。?這里需要驗證。修改superview的size,subview的size和position也會隨之改變。當你改變superview的size時,也可以控制subview的resizing工作。其他具有連帶效果的還有hide,修改superview的alpha(透明值),修改superview的坐標系統。
時間響應鏈:view-superview-ssuperview-sssuperview的方式向上傳遞,當遇到能處理該事件的時候停止向上傳遞,如果都不能處理,那么回傳至application object(通常情況下是丟棄)。
Specific views can also pass the event object to an intervening responder object, such as a view controller.
1.1.2 The View Drawing Cycle
UIView class使用on-demand請求式繪制模型。當view第一次出現在屏幕上時,先繪制后保存快照。如果view的content沒發生變化,那么會一直使用這個快照。一旦修改了content,通知系統view已經發生改變,繪制view,保存快照。重繪時,不用直接redraw,而是使用setNeedsDisplay、setNeedsDisplayInRect這兩個方法。他們通知系統,view的content發生了改變,下一次繪制周期需要重新繪制。系統等到當前runloop完成后,開始初始化繪制工作。這一延遲給你提供了機會來做add、remove、hide、resize等工作。在這期間的修改,會在一個時間點來繪制。值得注意的是,修改view的形狀(大小?)不會引起系統重繪view。這一點由Content Mode來決定。大部分的ContentMode只是針對快照做拉伸等操作,而不是重新繪制生成快照。
UIView子類一般使用drawRect來定義如何繪制。
1.1.3 Content Modes
默認值:UIViewContentModeScaleToFill
當設置為UIViewContentModeRedraw ,那么每次都會重繪并更新快照。
1.1.4 Stretchable Views
contentStretch,在UIViewContentModeScaleToFill, UIViewContentModeScaleAspectFit, and UIViewContentModeScaleAspectFill這三種模式下生效,其他模式無效。
Stretchable views作用在Core Animation Layer上,具有較好的性能。(當設置view的背景時,直接設置stretchable比設置stretchableview具有更好的性能)
1.1.5 Built-In Animation Support(內置Animation支持)
由于每個UIView都有一個layer,設置動畫的時候很方便。UIView可以設置動畫的屬性有:frame,bounds,center,transform,alpha,backgroundColor,contentStretch
1.2 View Geometry and Coordinate Systems(View的坐標系統)
坐標的三個體系:screen坐標,window坐標,view坐標。因為window和view都有自己的坐標體系,任何時候都要意識到,是在哪個坐標系上做修改。繪制的時候,使用的是view自己的坐標系;geometry改變時,使用的是superview的坐標系。UIWindow和UIView都提供了轉換坐標系的函數。
有一些iOS技術使用了與UIKit不同的坐標原點。如Core Graphics and OpenGL ES使用的坐下坐標原點,y軸向上。
1.2.1 The Relationship of the Frame,Bounds,and Center Properties
- The frame property contains the frame rectangle, which specifies the size and location of the view in its superview’s coordinate system.---view在其superview坐標系中的size和location
- The bounds property contains the bounds rectangle, which specifies the size of the view (and its content origin) in the view’s own local coordinate system.--view本地坐標系中的size(這個size和frame中的size相同嗎?)
- The center property contains the known center point of the view in the superview’s coordinate system.--view在其superview坐標系中的center
通常使用frame和center來設置view。當只需要修改位置時,修改center即可。center的值在任何時候都有效,即使當前view上加了scaling和rotation設置,而frame不一樣,其在某些時候無效。
三者是相關聯的,所以,某一個屬性變化之后會引起其他兩個屬性值的變化,如下所列:
- When you set the frame property, the size value in the bounds property changes to match the new size of the frame rectangle. The value in the center property similarly changes to match the new center point of the frame rectangle.
- When you set the center property, the origin value in the frame changes accordingly.
- When you set the size of the bounds property, the size value in the frame property changes to match the new size of the bounds rectangle.
默認情況下,view的frame不會隨著superview 的frame來剪切。任何超出superview frame的view 的內容都會繪制。可以通過設置superview 的clipsToBounds - YES來修改這一現象。無論superview 的clip設置與否,view的點擊事件只在superview 的bounds內生效。換而言之,任何發生在superview bounds之外的點擊事件不會傳遞給當事view。
1.2.2 Coordinate System Transformations
affine transform 是一個數字矩陣,實現point從一個坐標系到另一個坐標系的轉換。可使用affine transform來修改整個view在superview中的size,location,orientation,還可以用在drawing code中控制某一單一塊。
transform--修改整個view
drawRect--修改某一塊內容
執行動畫也可以通過修改transform來實現,如讓view圍繞center旋轉,而不是通過修改size,frame這些屬性來實現。
Note: When modifying the transform property of your view, all transformations are performed relative to the center point of the view.
在drawRect中,通過修改affine transform來改變object的位置比在新位置創建object要快得多。(這一段需要理解。create each object relative to a fixed point, typically (0, 0), and use a transform to position the object immediately prior to drawing更快,什么意思?結合代碼理解。)使用CGContextGetCTM函數來獲取affine transform,使用Core Graphics函數進行修改。
因為subview的坐標建立在superview 的坐標體系之上的。所以,當你修改view的transform屬性時,會影響到view和subviews。好在,這一修改只會影響最終展示在屏幕上的渲染。因為每個subview是繪制在view的bounds中,可以忽略superview在drawing和layout中的transform變化。
下圖展示了rotation如何產生聯動效果的。
在view的drawrect中,給shape一個45度的旋轉,這個shape產生了45度的旋轉。另外給一個45度旋轉給view,shape看起來像旋轉了90度。
更多參考《Drawing and Printing Guide for iOS.》