view
原文地址:
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009503-CH1-SW2
简单的摘要备忘,不准确的地方请参考原文。
View 的层次结构和 subview 管理
The View Drawing Cycle
Content Modes
Stretchable Views
Build-In Animation Support
Frame,Bounds, Center 属性之间的关系
坐标系转换
Points 和 Pixels
Views 不是总有一个相应的 controller
Minimize custom drawing
Take advantage of Content Mode
尽可能将你的 view 设置为不透明
Adjust Your View’s Drawing Behavior When Scrolling
Do Not Customize Controls by Embedding Subviews
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009503-CH1-SW2
简单的摘要备忘,不准确的地方请参考原文。
- Introduction
- View and Window Architecture
- 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
- 使用 Core Animation layer 对象对性能有很大影响。view 对象的绘制code 应该尽
- 量少调用。调用绘制 code 后,结果会被 Core Animation 缓存,尽可能在以后的操
- 做中重用这些缓存。重用这些已经存在的内容可以消除昂贵的绘制操作调用。尤其是
- 在动画当中。
View 的层次结构和 subview 管理
- 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 对象,
- 一般会被丢弃。
The View Drawing Cycle
- 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:
- 方法是常用的技巧。
Content Modes
- 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
- 你也可以指定你的 contentMode 属性值为 UIViewContentModeRedraw , 当你的订制view
- 发生几何变化时调用自己的方法绘制他们,系统会调用你 view 的 drawRect: 方法
- ,你应该避免使用这个方法,你也不能将这个属性值用在系统标准view 中。
Stretchable Views
- 你可以指定你 view 的一部分是可伸缩的,当 view 的大小变化时,只有伸缩部分受影响,
- 一般在button 或者 view 只有部分定义为可重复的,Figure 1.3
- Figure1-3 Streching the backgroud of a button
- 使用 contentStretch 属性指定 view 的可伸缩区域。
Build-In Animation Support
- 每个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.
- UIKit 默认的坐标系统是,原点在 top-left cornet (左上角),坐标轴向下,向右延伸
- 坐标值用浮点数表示。 Figure1-4 表示相对于screen 的坐标系统。除了 screen 的坐标
- 系统外, window 和 view 定义了自己的本地坐标系统。允许你根据view 的本地坐标系统
- 定位,而不是screen 的坐标系统。
- Figure 1-4 Coordinate system orientation in UIKit
- 因为每个 window 和 view 都有自己的本地坐标系统。你应该意识到是哪个坐标系统在
- 起作用。每次你绘制 view 或者改变它的几何属性,你都是相对于某个坐标系统。
- 绘制的时候你指定 view 自身的坐标系统。改变几何属性的时候你根据 superview的
- 坐标系统。 UIWindow 和 UIView 类都有将坐标系统从一个转换为另一个的方法。
- 注意:
- 一些 iOS 技术默认的坐标系统和 UIKit 不同。例如: Core Graphics 和 OpenGL ES,
- 坐标原点在左下角,y 轴是向上延伸的。
Frame,Bounds, Center 属性之间的关系
- 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 属性间的关系
- 尽管可以单独修改 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
坐标系转换
- 坐标系转换为修改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
- 注意:
- 当 view 的 transform 属性不是 identity transform. view 的 frame 属性是 undefined
- ,需要忽略。 当一个 view 进行 transform, 位置和大小需要通过 center 和 bounds
- 属性获得。 subview 的 frame 依然有效。
Points 和 Pixels
- 在 iOS 中,坐标系的值是和距离是浮点数,单位是 Points, 这个设备间是不同的。是个
- 相对值。
- Table 1-1
Device | Screen dimensions (in Points) with * height |
iPhone and iTouch | 320 * 480 |
iPad | 768 * 1024 |
- 记住:
- one Point 没有必要对应屏幕上的 one Pixel
- 对于 device level 你指定的 Point 会被转换为 Pixel ,但这一般由系统完成。
- 3.
- 当用户和界面交互或者你的程序通过代码改变了一写内容,UIKit 内部会发生一系列
- 复杂的事件来响应交互。UIKit 会调用你的 view, 作为你的 app 对用户事件的响应
- Figure1-7 展示了一系列事件,从用户 touch 屏幕开始,到系统更新了屏幕内容作为
- 响应。
- Figure1-7 UIKit interactions with your objects
- 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.
- 如果标准 view 不能满足你的需求,你可以定义 custom view, 担需要你保证 custom
- view 的性能足够好。
- 注意: 在优化你的绘制代码前,你需要收集当前 view 的性能数据,收集数据可与让你
- 知道当前是否有性能问题。也可以得到一个优化代码前的基线。
Views 不是总有一个相应的 controller
- 你的 app 中 view 和 view controller 对象之间不是一对一的关系。view controller 的职责是管理 view hierarchy. 一般包含多个 view .
- 当设计你的 app 的界面时,你需要清楚 view controller 扮演的角色。
- view controller 提供了很多重要的行为,例如,协助 view 展示在屏幕上,
- 协助从屏幕上移除 view, 当收到 low-memory 警告时负责释放内存,当设备旋转
- 时改变界面的方向,等
Minimize custom drawing
- 尽量少的使用 custom drawing code, 有时你可能需要自定义的 drawing code,
- 当系统的标准 view 没有提供你想要的界面。但是如果你的 view 可以通过组合系统
- 标准 view 来实现,你应该优先选择组合系统的 view.
Take advantage of Content Mode
- Content modes 最小化你重画 view 的时间,默认 view 使用 UIViewContentModeScaleToFill content mode, 这个是 view's content 去
- 充满 view's frame 矩形。随着 content 不同,你可以改变这个属性,但是你应该
- 尽量避免使用 UIViewContentModeRedraw, 不管你使用哪种content mode属性,都
- 可以通过调用方法 setNeedsDisplay 和 setNeedsDisplayInRect 来强制view 重
- 画 content.
尽可能将你的 view 设置为不透明
- UIKit 通过 opaque 属性来判断 view 在组合时能否进行优化,
Adjust Your View’s Drawing Behavior When Scrolling
Do Not Customize Controls by Embedding Subviews
- Windows
- views
- Animations