原文地址:
[url]http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009503-CH1-SW2[/url]
简单的摘要备忘,不准确的地方请参考原文。
[list]
[*][b]Introduction[/b]
[*][b]View and Window Architecture[/b]
1.View Architecture Fundamentals (View 架构基础)
View 和 Window 的架构
Views 和 Windows 提供你 app 的用户界面并且处理界面上的交互事件。UIKit 框架
和其他系统框架提供了大量的 view 类,你可以直接使用或稍加简单的修改使用。如果标
准 view 无法满足你的需求,你可以自定义 custom view 来使用。
无论是使用系统views 或 custom view 你都需要懂得 UIView 和 UIWindow 类提供
的底层基础。这些类提供了复杂的功能来布局和展现 views.了解这些类的底层工作有助于
你app 中的views 可以在程序发生变化的时候正确工作。
View Architectrue 基础
大部分在 app 中的可视化内容是 UIView 对象的实例。 View 对象是在屏幕中定义的一
快矩形区域,并负责该区域的绘制和处理该区域的 touch event.一个 View 可以作为其
它 views 的 parent, 负责这些 subview 的定位和大小设置。 UIView 类定义的方法
做了大部分这些 views 间的关系管理工作,当然也可以根据需要自定义UIView 的行为。
View 对象与一个Core Animation layer 对象一起工作,他负责 View 的展现和动画,
每一个 UIKit View 背后都有一个 layer 对象(一般是 CALayer 类的实例),它负责View 的
背景存储和动画相关。一般你的操作都是通过 UIView 提供的接口。然而,当需要更多
的呈现和动画相关操作时可以直接调用 layer 对象。
为了了解 View 和 Layer 之间的关系。下面看一个例子 Figure 1-1 是例子 ViewTransitions 的 View 架构。这个例子中的 View 包括一个 window (window 也是一个
view ) , 一个普通的 UIView 对象作为 container view, 一个 image view, 一个
toolbar 展示控件。和一个 bar button item (它不是一个view , 但是它内部管理了一个
view ) 。 每个 view 都包含一个可以被访问的 layer 属性。在 layer 对象背后是
Core Animaition 展示对象和 硬件 buffer 最终管理显示的 bits.
Figure 1-1 Architecture of the views in a sample application
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/view-layer-store.jpg[/img]
使用 Core Animation layer 对象对性能有很大影响。view 对象的绘制code 应该尽
量少调用。调用绘制 code 后,结果会被 Core Animation 缓存,尽可能在以后的操
做中重用这些缓存。重用这些已经存在的内容可以消除昂贵的绘制操作调用。尤其是
在动画当中。
[b]View 的层次结构和 subview 管理[/b]
View 除了提供自己的内容,还可以作为其他 view 的容器。当一个view 包含其他的
view。他们之间就建立了一种 parent - child 关系。child 是 subview, parent 是
superview.这个意思是会影响 parent - child view 之间的展现和行为。
视觉上,subview 会部分或全部覆盖 superview 的内容。如果subview 是不透明的它
会完全覆盖 superview 相应的部分。如果 subview 是部分透明的,会显示 subview
和 superview 叠加在一起的内容。 subviews 保持在 superview 的一个有序数组中
(order array)。 subview 在数组中的顺序也会影响显示,后加入的subview 在上面。
view hierarchy 中view 的布局决定你的应用如何响应 events.发生在一个特定 view
的 touch event 事件。系统首先给这个 view 发送一个包含 touch 信息的 event.如果
这个 view 没有处理这个 touch event, touch event 会被传递给他的 superview
, 如果super view 也没有处理,则传给 superview 的 superview.沿着 responder chain
传递事件。 specific view 也可以将事件传递给一个 responder object, 例如
view controller 对象。如果没有对象处理这个事件,最终事件到达 application 对象,
一般会被丢弃。
[b]The View Drawing Cycle[/b]
UIView 类使用一种 on-command 模型来展示内容。当一个 view 第一次出现在 screen
中,系统要求 view 绘制它的内容。系统抓取一个内容的快照,使用快照作为 view 的
可视内容。如果view 的内容不变,那么 view 的绘制 code 将不会再调用。快照的图片
会被重用在大多数场合,如果改变了 view 的内容,你通知系统 view 改变了,系统会
重复之前的过程,绘制 view ,然后抓取快照。
当 view 的内容改变了,你不是直接绘制这些变化,而是,将你的view 标为无效,通过
调用方法 setNeedsDisplay 或 setNeedsDisplayInRect 。 这些方法会告诉系统 view
的内容已经变化,需要下次重新绘制。系统等到当前的 run loop 结束,然后初始化绘制
操作。这个延时可以使你有机会一次将多个 view 标为 invalidate, 在你的 view hierarchy
增加或者删除 view , 改变view 的大小或者位置,你做的所有变化都会同时展现出来。
注意:在几何上改变 view 不会自动导致系统重画 view 内容。view 的 contentMode 属性
决定几何上改变 view 将被如何解释。
当到绘制 view 内容的时刻,实际绘制过程依赖于view 和它的配置。系统view 一般通过
private 方法绘制 view 内容。你可以通过一些接口来配置 view 的展示,如果订制
实现 UIView 的子类,你需要覆盖 drawRect: 方法,通过这个方法来绘制你的 view
内容。也可用其他的方法比如直接设置底层 layer 上的内容。不过覆盖 drawRect:
方法是常用的技巧。
[b]Content Modes[/b]
View 通过 content mode 来控制在 view 几何变化时如何 recyle view 的内容,或者
是否 recyle view 的内容。当一个 view 首次展示,view 会被抓取一个 bitmap,
之后 view 的几何变化不会总是导致 bitmap 的重建,content mode 决定 bitmap 是否
扩展到新边界或是移动到一角或一边。
在做如下操作时,会应用 content mode
* 改变 frame 或 bounds 矩形的 with 或 height
* 给view 的 transform 分配一个 transform
默认情况,View 的 contentMode 属性是 UIViewContentModeScaleToFill, 这会是view
的内容拉伸来适应新的大小。 Figure 1-2 展示了不同 contentMode 值,如何展示 view.
Figure1-2 Content mode cpmparisions
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/scale_aspect.jpg[/img]
你也可以指定你的 contentMode 属性值为 UIViewContentModeRedraw , 当你的订制view
发生几何变化时调用自己的方法绘制他们,系统会调用你 view 的 drawRect: 方法
,你应该避免使用这个方法,你也不能将这个属性值用在系统标准view 中。
[b]Stretchable Views[/b]
你可以指定你 view 的一部分是可伸缩的,当 view 的大小变化时,只有伸缩部分受影响,
一般在button 或者 view 只有部分定义为可重复的,Figure 1.3
Figure1-3 Streching the backgroud of a button
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/button_scale.jpg[/img]
使用 contentStretch 属性指定 view 的可伸缩区域。
[b]Build-In Animation Support[/b]
每个view 后面有一个 layer 对象的另一个好处是,你可以使用很多属性变化动画效果。
很多UIView 的属性都是可以有动画效果的。为了让一个可以动画的 view 属性执行动画
效果,你需要:
1. 告诉 UIKit 你想要执行一个动画效果
2. 改变属性的值
可以应用动画效果的 View 属性包扩:
frame- 动画效果展示 view 的位置和大小变化
bounds - 动画效果展示 view 的大小变化
center - 动画效果展示 view 的位置变化
transform - 动画效果展示 view 的转化或尺寸变化
alpha - 动画效果展示 view 的透明度变化
backgroundColor -动画效果展示 view 的背景色变化
contentStretch - 动画效果展示 view 的拉伸变化
你也可以通过 UIKit 框架的 Core Animation layers 来制作动画
2.[b]View Geometry and Coordinate Systems [View 的几何和坐标系统][/b]
UIKit 默认的坐标系统是,原点在 top-left cornet (左上角),坐标轴向下,向右延伸
坐标值用浮点数表示。 Figure1-4 表示相对于screen 的坐标系统。除了 screen 的坐标
系统外, window 和 view 定义了自己的本地坐标系统。允许你根据view 的本地坐标系统
定位,而不是screen 的坐标系统。
Figure 1-4 Coordinate system orientation in UIKit
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/native_coordinate_system.jpg[/img]
因为每个 window 和 view 都有自己的本地坐标系统。你应该意识到是哪个坐标系统在
起作用。每次你绘制 view 或者改变它的几何属性,你都是相对于某个坐标系统。
绘制的时候你指定 view 自身的坐标系统。改变几何属性的时候你根据 superview的
坐标系统。 UIWindow 和 UIView 类都有将坐标系统从一个转换为另一个的方法。
注意:
一些 iOS 技术默认的坐标系统和 UIKit 不同。例如: Core Graphics 和 OpenGL ES,
坐标原点在左下角,y 轴是向上延伸的。
[b]Frame,Bounds, Center 属性之间的关系[/b]
view 通过 frame, bounds, center 属性定义大小和位置
* frame 属性,包含 frame 矩形,指定 view 在它 superview 坐标系中的位置和大小
* bounds 属性,包含bounds 矩形,指定 view 在本地坐标系中的大小
* center 属性,包含 view 在superview 中的 center point 坐标。
使用 center 和 frame 属性来主要操作 view 的几何变化。例如,构建你的 view
hierarchy , 或在运行时改变 view 的大小和位置。如果只是改变 view 的位置(不
包括大小), 改变 center 属性是最好的方法。center 属性的值总是有效的,即使
改变view 的 scale 或旋转。 然后 frame 属性中的位置值不一定有效。
使用 bounds 属性来绘制,bounds 矩形根据 view 的本地坐标系统。
Figure1-5 view 的 frame 和 bounds 属性间的关系
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/frame_bounds_rects.jpg[/img]
尽管可以单独修改 frame, bounds,center 属性中的一个,但是可能会影响其他属性:
* 当设置 frame 属性,bounds 属性的长宽的大小也被设置为和 frame 一样,center
属性的值和新 frame 的 center point 相同。
* 当设置 center 属性, frame 的 center point 也会相应修改
* 当设置 bounds 的长宽,frame 的 szie 也会相应变化。
默认情况下, view 的 frame 不会根据他 superview 的frame 剪裁,就是说 subview
超出 superview 的部分会被显示出来,可以通过设置 superview 的 clipToBounds 属性
为 YES
[b]坐标系转换[/b]
坐标系转换为修改view 提供了一个快速、简单的方法。一个 affine 转换,指定了一个
point 如何从一个坐标系映射到另一个坐标系。
* 修改 transform 属性
* 修改 view 的 drawRect: 方法
通过 修改 transform 属性可以实现动画效果,例如 view 按照 center point 旋转,
不能通过这个属性进行view 的永久变化。永久变化需要修改 frame 属性。
subview 的坐标系建立在它的父坐标系基础上,因此当修改 view 的 transform 属性,
会影响所有的subview
Figure 1-6 Rotating a view and its content
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/xform_rotations.jpg[/img]
注意:
当 view 的 transform 属性不是 identity transform. view 的 frame 属性是 undefined
,需要忽略。 当一个 view 进行 transform, 位置和大小需要通过 center 和 bounds
属性获得。 subview 的 frame 依然有效。
[b]Points 和 Pixels[/b]
在 iOS 中,坐标系的值是和距离是浮点数,单位是 Points, 这个设备间是不同的。是个
相对值。
Table 1-1
[table]
|Device|Screen dimensions (in Points) with * height|
|iPhone and iTouch| 320 * 480|
|iPad| 768 * 1024|
[/table]
记住:
one Point 没有必要对应屏幕上的 one Pixel
对于 device level 你指定的 Point 会被转换为 Pixel ,但这一般由系统完成。
3.[b]The Runtime interaction Model for Views[/b]
当用户和界面交互或者你的程序通过代码改变了一写内容,UIKit 内部会发生一系列
复杂的事件来响应交互。UIKit 会调用你的 view, 作为你的 app 对用户事件的响应
Figure1-7 展示了一系列事件,从用户 touch 屏幕开始,到系统更新了屏幕内容作为
响应。
Figure1-7 UIKit interactions with your objects
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/drawing_model.jpg[/img]
1. 用户触发屏幕 touch 事件
2. 硬件将屏幕 touch 事件报告给 UIKit framework
3. UIKit 框架讲 touch 事件包装为一个 UIEvent 对象,并分发给响应的 view
4. 你 view 中的事件处理代码响应事件,例如:
改变 view 和 subviews 的 properties (frame, bounds, alpha, ...)
调用方法 setNeedsLayout, 将 view 标记为需要更新布局。
调用方法 setNeedsDisplay 或 setNeedsDisplayInRect 将 view 标记为
需要重新绘制
通知 controller 改变一些数据
5. 如果 view 的几何属性发生了变化,UIKit 根据如下规则更新 subviews:
a. 如果你的 view 配置了 autoresizing rules, UIKit 会根据这个规则调整
每个 view
b. 如果你的 view 实现了 layoutSubviews 方法, UIKit 会调用它
6. 如果你的 view 任何部分标记为需要 redrawn. UIKit 会要求 view 重画自己。
7. 更新的 view 会和 app 的其他可视部分发送给硬件显示
8. 硬件将内容展示在屏幕上。
事件处理方法
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancled:withEvent:
layoutSubviews: 方法
drawRect: 方法
4.[b]Tips for Using Views Effectively[/b]
如果标准 view 不能满足你的需求,你可以定义 custom view, 担需要你保证 custom
view 的性能足够好。
注意: 在优化你的绘制代码前,你需要收集当前 view 的性能数据,收集数据可与让你
知道当前是否有性能问题。也可以得到一个优化代码前的基线。
[b]Views 不是总有一个相应的 controller [/b]
你的 app 中 view 和 view controller 对象之间不是一对一的关系。view controller 的职责是管理 view hierarchy. 一般包含多个 view .
当设计你的 app 的界面时,你需要清楚 view controller 扮演的角色。
view controller 提供了很多重要的行为,例如,协助 view 展示在屏幕上,
协助从屏幕上移除 view, 当收到 low-memory 警告时负责释放内存,当设备旋转
时改变界面的方向,等
[b]Minimize custom drawing[/b]
尽量少的使用 custom drawing code, 有时你可能需要自定义的 drawing code,
当系统的标准 view 没有提供你想要的界面。但是如果你的 view 可以通过组合系统
标准 view 来实现,你应该优先选择组合系统的 view.
[b]Take advantage of Content Mode[/b]
Content modes 最小化你重画 view 的时间,默认 view 使用 UIViewContentModeScaleToFill content mode, 这个是 view's content 去
充满 view's frame 矩形。随着 content 不同,你可以改变这个属性,但是你应该
尽量避免使用 UIViewContentModeRedraw, 不管你使用哪种content mode属性,都
可以通过调用方法 setNeedsDisplay 和 setNeedsDisplayInRect 来强制view 重
画 content.
[b]尽可能将你的 view 设置为不透明[/b]
UIKit 通过 opaque 属性来判断 view 在组合时能否进行优化,
[b]Adjust Your View’s Drawing Behavior When Scrolling[/b]
[b]Do Not Customize Controls by Embedding Subviews [/b]
[*][b]Windows[/b]
[*][b]views[/b]
[*][b]Animations[/b]
[/list]
[url]http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009503-CH1-SW2[/url]
简单的摘要备忘,不准确的地方请参考原文。
[list]
[*][b]Introduction[/b]
[*][b]View and Window Architecture[/b]
1.View Architecture Fundamentals (View 架构基础)
View 和 Window 的架构
Views 和 Windows 提供你 app 的用户界面并且处理界面上的交互事件。UIKit 框架
和其他系统框架提供了大量的 view 类,你可以直接使用或稍加简单的修改使用。如果标
准 view 无法满足你的需求,你可以自定义 custom view 来使用。
无论是使用系统views 或 custom view 你都需要懂得 UIView 和 UIWindow 类提供
的底层基础。这些类提供了复杂的功能来布局和展现 views.了解这些类的底层工作有助于
你app 中的views 可以在程序发生变化的时候正确工作。
View Architectrue 基础
大部分在 app 中的可视化内容是 UIView 对象的实例。 View 对象是在屏幕中定义的一
快矩形区域,并负责该区域的绘制和处理该区域的 touch event.一个 View 可以作为其
它 views 的 parent, 负责这些 subview 的定位和大小设置。 UIView 类定义的方法
做了大部分这些 views 间的关系管理工作,当然也可以根据需要自定义UIView 的行为。
View 对象与一个Core Animation layer 对象一起工作,他负责 View 的展现和动画,
每一个 UIKit View 背后都有一个 layer 对象(一般是 CALayer 类的实例),它负责View 的
背景存储和动画相关。一般你的操作都是通过 UIView 提供的接口。然而,当需要更多
的呈现和动画相关操作时可以直接调用 layer 对象。
为了了解 View 和 Layer 之间的关系。下面看一个例子 Figure 1-1 是例子 ViewTransitions 的 View 架构。这个例子中的 View 包括一个 window (window 也是一个
view ) , 一个普通的 UIView 对象作为 container view, 一个 image view, 一个
toolbar 展示控件。和一个 bar button item (它不是一个view , 但是它内部管理了一个
view ) 。 每个 view 都包含一个可以被访问的 layer 属性。在 layer 对象背后是
Core Animaition 展示对象和 硬件 buffer 最终管理显示的 bits.
Figure 1-1 Architecture of the views in a sample application
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/view-layer-store.jpg[/img]
使用 Core Animation layer 对象对性能有很大影响。view 对象的绘制code 应该尽
量少调用。调用绘制 code 后,结果会被 Core Animation 缓存,尽可能在以后的操
做中重用这些缓存。重用这些已经存在的内容可以消除昂贵的绘制操作调用。尤其是
在动画当中。
[b]View 的层次结构和 subview 管理[/b]
View 除了提供自己的内容,还可以作为其他 view 的容器。当一个view 包含其他的
view。他们之间就建立了一种 parent - child 关系。child 是 subview, parent 是
superview.这个意思是会影响 parent - child view 之间的展现和行为。
视觉上,subview 会部分或全部覆盖 superview 的内容。如果subview 是不透明的它
会完全覆盖 superview 相应的部分。如果 subview 是部分透明的,会显示 subview
和 superview 叠加在一起的内容。 subviews 保持在 superview 的一个有序数组中
(order array)。 subview 在数组中的顺序也会影响显示,后加入的subview 在上面。
view hierarchy 中view 的布局决定你的应用如何响应 events.发生在一个特定 view
的 touch event 事件。系统首先给这个 view 发送一个包含 touch 信息的 event.如果
这个 view 没有处理这个 touch event, touch event 会被传递给他的 superview
, 如果super view 也没有处理,则传给 superview 的 superview.沿着 responder chain
传递事件。 specific view 也可以将事件传递给一个 responder object, 例如
view controller 对象。如果没有对象处理这个事件,最终事件到达 application 对象,
一般会被丢弃。
[b]The View Drawing Cycle[/b]
UIView 类使用一种 on-command 模型来展示内容。当一个 view 第一次出现在 screen
中,系统要求 view 绘制它的内容。系统抓取一个内容的快照,使用快照作为 view 的
可视内容。如果view 的内容不变,那么 view 的绘制 code 将不会再调用。快照的图片
会被重用在大多数场合,如果改变了 view 的内容,你通知系统 view 改变了,系统会
重复之前的过程,绘制 view ,然后抓取快照。
当 view 的内容改变了,你不是直接绘制这些变化,而是,将你的view 标为无效,通过
调用方法 setNeedsDisplay 或 setNeedsDisplayInRect 。 这些方法会告诉系统 view
的内容已经变化,需要下次重新绘制。系统等到当前的 run loop 结束,然后初始化绘制
操作。这个延时可以使你有机会一次将多个 view 标为 invalidate, 在你的 view hierarchy
增加或者删除 view , 改变view 的大小或者位置,你做的所有变化都会同时展现出来。
注意:在几何上改变 view 不会自动导致系统重画 view 内容。view 的 contentMode 属性
决定几何上改变 view 将被如何解释。
当到绘制 view 内容的时刻,实际绘制过程依赖于view 和它的配置。系统view 一般通过
private 方法绘制 view 内容。你可以通过一些接口来配置 view 的展示,如果订制
实现 UIView 的子类,你需要覆盖 drawRect: 方法,通过这个方法来绘制你的 view
内容。也可用其他的方法比如直接设置底层 layer 上的内容。不过覆盖 drawRect:
方法是常用的技巧。
[b]Content Modes[/b]
View 通过 content mode 来控制在 view 几何变化时如何 recyle view 的内容,或者
是否 recyle view 的内容。当一个 view 首次展示,view 会被抓取一个 bitmap,
之后 view 的几何变化不会总是导致 bitmap 的重建,content mode 决定 bitmap 是否
扩展到新边界或是移动到一角或一边。
在做如下操作时,会应用 content mode
* 改变 frame 或 bounds 矩形的 with 或 height
* 给view 的 transform 分配一个 transform
默认情况,View 的 contentMode 属性是 UIViewContentModeScaleToFill, 这会是view
的内容拉伸来适应新的大小。 Figure 1-2 展示了不同 contentMode 值,如何展示 view.
Figure1-2 Content mode cpmparisions
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/scale_aspect.jpg[/img]
你也可以指定你的 contentMode 属性值为 UIViewContentModeRedraw , 当你的订制view
发生几何变化时调用自己的方法绘制他们,系统会调用你 view 的 drawRect: 方法
,你应该避免使用这个方法,你也不能将这个属性值用在系统标准view 中。
[b]Stretchable Views[/b]
你可以指定你 view 的一部分是可伸缩的,当 view 的大小变化时,只有伸缩部分受影响,
一般在button 或者 view 只有部分定义为可重复的,Figure 1.3
Figure1-3 Streching the backgroud of a button
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/button_scale.jpg[/img]
使用 contentStretch 属性指定 view 的可伸缩区域。
[b]Build-In Animation Support[/b]
每个view 后面有一个 layer 对象的另一个好处是,你可以使用很多属性变化动画效果。
很多UIView 的属性都是可以有动画效果的。为了让一个可以动画的 view 属性执行动画
效果,你需要:
1. 告诉 UIKit 你想要执行一个动画效果
2. 改变属性的值
可以应用动画效果的 View 属性包扩:
frame- 动画效果展示 view 的位置和大小变化
bounds - 动画效果展示 view 的大小变化
center - 动画效果展示 view 的位置变化
transform - 动画效果展示 view 的转化或尺寸变化
alpha - 动画效果展示 view 的透明度变化
backgroundColor -动画效果展示 view 的背景色变化
contentStretch - 动画效果展示 view 的拉伸变化
你也可以通过 UIKit 框架的 Core Animation layers 来制作动画
2.[b]View Geometry and Coordinate Systems [View 的几何和坐标系统][/b]
UIKit 默认的坐标系统是,原点在 top-left cornet (左上角),坐标轴向下,向右延伸
坐标值用浮点数表示。 Figure1-4 表示相对于screen 的坐标系统。除了 screen 的坐标
系统外, window 和 view 定义了自己的本地坐标系统。允许你根据view 的本地坐标系统
定位,而不是screen 的坐标系统。
Figure 1-4 Coordinate system orientation in UIKit
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/native_coordinate_system.jpg[/img]
因为每个 window 和 view 都有自己的本地坐标系统。你应该意识到是哪个坐标系统在
起作用。每次你绘制 view 或者改变它的几何属性,你都是相对于某个坐标系统。
绘制的时候你指定 view 自身的坐标系统。改变几何属性的时候你根据 superview的
坐标系统。 UIWindow 和 UIView 类都有将坐标系统从一个转换为另一个的方法。
注意:
一些 iOS 技术默认的坐标系统和 UIKit 不同。例如: Core Graphics 和 OpenGL ES,
坐标原点在左下角,y 轴是向上延伸的。
[b]Frame,Bounds, Center 属性之间的关系[/b]
view 通过 frame, bounds, center 属性定义大小和位置
* frame 属性,包含 frame 矩形,指定 view 在它 superview 坐标系中的位置和大小
* bounds 属性,包含bounds 矩形,指定 view 在本地坐标系中的大小
* center 属性,包含 view 在superview 中的 center point 坐标。
使用 center 和 frame 属性来主要操作 view 的几何变化。例如,构建你的 view
hierarchy , 或在运行时改变 view 的大小和位置。如果只是改变 view 的位置(不
包括大小), 改变 center 属性是最好的方法。center 属性的值总是有效的,即使
改变view 的 scale 或旋转。 然后 frame 属性中的位置值不一定有效。
使用 bounds 属性来绘制,bounds 矩形根据 view 的本地坐标系统。
Figure1-5 view 的 frame 和 bounds 属性间的关系
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/frame_bounds_rects.jpg[/img]
尽管可以单独修改 frame, bounds,center 属性中的一个,但是可能会影响其他属性:
* 当设置 frame 属性,bounds 属性的长宽的大小也被设置为和 frame 一样,center
属性的值和新 frame 的 center point 相同。
* 当设置 center 属性, frame 的 center point 也会相应修改
* 当设置 bounds 的长宽,frame 的 szie 也会相应变化。
默认情况下, view 的 frame 不会根据他 superview 的frame 剪裁,就是说 subview
超出 superview 的部分会被显示出来,可以通过设置 superview 的 clipToBounds 属性
为 YES
[b]坐标系转换[/b]
坐标系转换为修改view 提供了一个快速、简单的方法。一个 affine 转换,指定了一个
point 如何从一个坐标系映射到另一个坐标系。
* 修改 transform 属性
* 修改 view 的 drawRect: 方法
通过 修改 transform 属性可以实现动画效果,例如 view 按照 center point 旋转,
不能通过这个属性进行view 的永久变化。永久变化需要修改 frame 属性。
subview 的坐标系建立在它的父坐标系基础上,因此当修改 view 的 transform 属性,
会影响所有的subview
Figure 1-6 Rotating a view and its content
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/xform_rotations.jpg[/img]
注意:
当 view 的 transform 属性不是 identity transform. view 的 frame 属性是 undefined
,需要忽略。 当一个 view 进行 transform, 位置和大小需要通过 center 和 bounds
属性获得。 subview 的 frame 依然有效。
[b]Points 和 Pixels[/b]
在 iOS 中,坐标系的值是和距离是浮点数,单位是 Points, 这个设备间是不同的。是个
相对值。
Table 1-1
[table]
|Device|Screen dimensions (in Points) with * height|
|iPhone and iTouch| 320 * 480|
|iPad| 768 * 1024|
[/table]
记住:
one Point 没有必要对应屏幕上的 one Pixel
对于 device level 你指定的 Point 会被转换为 Pixel ,但这一般由系统完成。
3.[b]The Runtime interaction Model for Views[/b]
当用户和界面交互或者你的程序通过代码改变了一写内容,UIKit 内部会发生一系列
复杂的事件来响应交互。UIKit 会调用你的 view, 作为你的 app 对用户事件的响应
Figure1-7 展示了一系列事件,从用户 touch 屏幕开始,到系统更新了屏幕内容作为
响应。
Figure1-7 UIKit interactions with your objects
[img]http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Art/drawing_model.jpg[/img]
1. 用户触发屏幕 touch 事件
2. 硬件将屏幕 touch 事件报告给 UIKit framework
3. UIKit 框架讲 touch 事件包装为一个 UIEvent 对象,并分发给响应的 view
4. 你 view 中的事件处理代码响应事件,例如:
改变 view 和 subviews 的 properties (frame, bounds, alpha, ...)
调用方法 setNeedsLayout, 将 view 标记为需要更新布局。
调用方法 setNeedsDisplay 或 setNeedsDisplayInRect 将 view 标记为
需要重新绘制
通知 controller 改变一些数据
5. 如果 view 的几何属性发生了变化,UIKit 根据如下规则更新 subviews:
a. 如果你的 view 配置了 autoresizing rules, UIKit 会根据这个规则调整
每个 view
b. 如果你的 view 实现了 layoutSubviews 方法, UIKit 会调用它
6. 如果你的 view 任何部分标记为需要 redrawn. UIKit 会要求 view 重画自己。
7. 更新的 view 会和 app 的其他可视部分发送给硬件显示
8. 硬件将内容展示在屏幕上。
事件处理方法
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancled:withEvent:
layoutSubviews: 方法
drawRect: 方法
4.[b]Tips for Using Views Effectively[/b]
如果标准 view 不能满足你的需求,你可以定义 custom view, 担需要你保证 custom
view 的性能足够好。
注意: 在优化你的绘制代码前,你需要收集当前 view 的性能数据,收集数据可与让你
知道当前是否有性能问题。也可以得到一个优化代码前的基线。
[b]Views 不是总有一个相应的 controller [/b]
你的 app 中 view 和 view controller 对象之间不是一对一的关系。view controller 的职责是管理 view hierarchy. 一般包含多个 view .
当设计你的 app 的界面时,你需要清楚 view controller 扮演的角色。
view controller 提供了很多重要的行为,例如,协助 view 展示在屏幕上,
协助从屏幕上移除 view, 当收到 low-memory 警告时负责释放内存,当设备旋转
时改变界面的方向,等
[b]Minimize custom drawing[/b]
尽量少的使用 custom drawing code, 有时你可能需要自定义的 drawing code,
当系统的标准 view 没有提供你想要的界面。但是如果你的 view 可以通过组合系统
标准 view 来实现,你应该优先选择组合系统的 view.
[b]Take advantage of Content Mode[/b]
Content modes 最小化你重画 view 的时间,默认 view 使用 UIViewContentModeScaleToFill content mode, 这个是 view's content 去
充满 view's frame 矩形。随着 content 不同,你可以改变这个属性,但是你应该
尽量避免使用 UIViewContentModeRedraw, 不管你使用哪种content mode属性,都
可以通过调用方法 setNeedsDisplay 和 setNeedsDisplayInRect 来强制view 重
画 content.
[b]尽可能将你的 view 设置为不透明[/b]
UIKit 通过 opaque 属性来判断 view 在组合时能否进行优化,
[b]Adjust Your View’s Drawing Behavior When Scrolling[/b]
[b]Do Not Customize Controls by Embedding Subviews [/b]
[*][b]Windows[/b]
[*][b]views[/b]
[*][b]Animations[/b]
[/list]