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.》