View Programming Guide For IOS 翻译

View Programming Guide For IOS 官方地址


View and Window Architecture(视图与窗口的结构)


View Architecture Fundamentals(视图的基础结构)


当你处理视图相关的问题时,最常接触到的类是UIView. View 对象在屏幕上定义了一块矩形区域.并且管理这块区域的点击事件. View 也可以作为其他 View 的父视图.并且管理对应子 View 位置和大小. UIView 类做了大量的管理各个视图的关系,你也可以自定义这些关系.

视图与 Core Animation 的 layer 结合在一起,用于管理视图动画内容相关.每个UIKIt中的视图下层都有 layer 对象 .管理下层储存和管理视图动画相关.大多数情况下,你执行相关的效果只需要使用 UIView 的公开属性就可以了.然后,如果你想得到更多的控制视图动画相关的能力,你可以使用视图的layer层.

为了更好的理解视图与layer相关,我们通过下面的例子来理解.

Core Animation 的 layer 对象的功能对底层的实现有影响.实际上绘制视图的代码尽可能少去调用.当代码被调用,绘制结果将被 Core Animation 缓存下来,并且尽可能的重用.重用已经绘制好的视图可以减少重新绘制视图所造成的额外消耗.重用机制在动画执行时有重要作用.

View Hierarchies and Subview Management


父视图通过数组来保存子视图,子视图在数组中的顺序是会影响视图的显示的
父视图中有两个子视图,这两个子视图有重叠部分,那么后添加(或者是被移动到数组最后)的视图将会显示在上面.
父视图子视图的关系也会影响视图行为,改变父视图的大小将会导致子视图的位置跟大小发生改变.其他改变也会影响子视图,比如:

1、隐藏父视图 
2、改变父视图的透明度
3、改变父视图的坐标系统

视图的排布决定了程序如何响应点击事件.
当一个点击事件发生在屏幕上时,系统将发送事件到对应的视图上,对应视图来处理事件.如果对应的视图没有处理事件的能力,那么事件将传给对应视图的父视图.如果父视图也不能处理,那么事件将传给父视图的父视图.以此类推.
这是一个响应者链 Response Chain .
视图也可以将事件传给交互的实体,比如viewController.
如果没有实体处理事件,事件最终将传给应用实体 (Application Object).它来统一丢弃(discard)

The View Drawing Cycle


UIView类是以 “按需绘图模式" 去展现内容.
当一个视图第一次展现在屏幕上时,系统会要求它去绘制自己的内容.
系统将获取View中内容的 snapshot(截屏)并用截屏 snapshot(截屏)作为视图的可视部分的代替.
如果你从未改变视图内容,那么视图绘制代码将不会被执行.
对应的 snapshot(截屏)会被重复利用.在大多数跟这个视图相关的操作中.如果你改变了视图的内容,你去通知系统对应的视图发生了改变.视图将重复绘制视图的过程并且获取视图新的截屏.

当视图的内容发生改变,你不需要直接去重新绘制视图.
你通过使setNeedsDisplaysetNeedsDisplayInRect:方法主动去作废之前的视图.
这些方法告诉系统视图的内容被修改了,在下个opportunity需要重新绘制.
系统将会在下次初始化绘制动作前和现在的runloop结束后重新绘制.
这个等待将会给你充分的时间去(invalidate)作废多个View,或者是从View层级中移除视图,隐藏视图,改变视图大小,改变视图位置.
所有你做的改变将会同时反应出来.

到了绘制 view 的内容的时机,真正决定绘制内容是取决于 view 和 view 的属性.
系统视图实现了私有的绘制方法,并在头部展示出来.
一些系统的视图类将接口暴露出来,你通过修改相关属性来控制视图的显示.
自定一个视图UIView子类,你可以通过重写子类中drawRect:方法,去绘制视图.还有其他方式来提供视图内容,比如直接设置内容的(underlying layer)下层.但是drawRect:方式是最通用实现方法.

Content Modes


每个view都有 content mode, content mode 的作用是在视图的坐标发生改变时,如果去回收利用内容。当一个view第一次被展示时,它的内容将会被捕获,捕获的结果以bitmap的形式.改变坐标系时,bitmap将不会被重新绘制. content mode 属性决定bitmap该如何被拉伸。或者仅仅只是移动位置。

视图的 Content Mode 将被应用在下面的情况

  • 当你改变 frame 或者 bounds 的高和宽时,将会应用 contentmode.
  • 当修改 View 的 transform 属性时,transform 属性包含放大所有的因素时。

大多数view的 contentmode 是 UIViewContentModeScaleToFill

请自行查找 contentmode 各个值

StretchableViews(可拉伸区域)


你可以定义一块区域作为可拉伸的区域,当view的大小改变时,只有在可拉伸区域的内容受到影响.

经常人们会定义一个可拉伸区域,作为试图的一个重复的模块

可拉伸区域可以从xy轴两个方向拉伸

通过contentStretch属性来申明一个可拉伸的区域,值的范围是0~1

contentmodel在可拉伸区中如何拉伸中起到很重要的作用.可拉伸区域只有在contentmode导致视图内容被放大或者缩小时.

这意味着只有在contentmode为以下内容时才可以被拉伸:

  • UIViewContentModeScaleToFill,
  • UIViewContentModeScaleAspectFit,
  • UIViewContentModeScaleAspectFill

Built-In Animation Support


在每一个视图(View)下面都有一个 layer (图层)的好处是,我们可以很容易完成跟view相关的动画.
想要执行一个动画,你必须要做一下两个步骤.

  1. 告诉UIKIt,将要执行一个动画
  2. 改变属性的值

改变以下UIView属性时,将会有动画

  • frame — Use this to animate position and size changes for the view.

  • bounds — Use this to animate changes to the size of the view.

  • center — Use this to animate the position of the view.

  • transform — Use this to rotate or scale the view.

  • alpha — Use this to change the transparency of the view.

  • background Color — Use this to change the background color of the view.

  • content Stretch — Use this to change how the view’s contents stretch.

Core Animation 将会告诉你如何开发动画

视图的几何意义上的坐标系

在UIkit中以左上角为坐标原点,使用 floating point number

每一个view和屏幕都有自己的坐标系。

The Relationship of the Frame,Bounds,and Center Properties

视图

默认情况下,子视图超出父视图时,父视图将不会裁剪子视图.你可以设置clipsToBounds,来改变这个效果.
不管子视图有没有超区父视图,当事件传过来时,只会在父视图的frame中响应。

Points Versus Pixels 点与像素之间的关系

Points(点)提供一个frame(矩形区域)用来绘图。
ios是一个以点为计量单位来定义了用户坐标空间的系统
一个点并不是代表一个在屏幕上的像素

The Runtime Interaction Model for Views 运行时交互

当用户点击你的交互界面,或者你代码修改一些object,一系列复杂的事件将要被触发在UIKit中,来管理交互.这些事件是有序列的。在UIKit调用这个特定序列的事件中特殊时期,UIKit将会调用你的类,来让你的类处理对应的交互事件。
下面是这个事件队列。

View Programming Guide For IOS 翻译_第1张图片
sequence of event
  1. 用户点击屏幕

  2. 硬件报告事件给UIKit

  3. UIKit打包touch事件到UIEvent事件,并将对应事件发送到对应的视图。

  4. 视图的事件处理代码将被触发来回应对应的事件。

    • 改变视图的属性
    • 调用setNeedsLayout方法 标记view需要 layout
    • 调用setNeedsDisplay: 或者 setNeedsDisplayInRect:去标记视图需要重新绘制
    • 通知视图控制器去改变部分数据
  5. 如果视图的几何坐标修改了,UIKit需要根据下面的规则更新它的子视图。

    • 如果你设置 autoresizing,那么UIKit将会根据你的设置来调整视图。
    • 如果你的视图实现了layoutSubviews 方法,UIKit将会调用它。
      • 你可以重写此方法来自定义视图。使用本方法来调整子视图位置和大小。举个例子,视图提供一个大的滑动区域。
  6. 如果任何一个视图被标记为重新绘制,UIKit将会要求视图去重写绘制

  7. 任何更新完之后的视图将被复合成对应区域的内容,发给绘图硬件绘制。

  8. 绘图硬件将绘制完好的内容展现到屏幕上。

总结一下如何自定义一个视图

  1. 事件响应方法

    • -touchesBegan:withEvent:
    • -touchesMoved:withEvent:
    • -touchesEnded:withEvent:
    • -touchesCancelled:withEvent:
  2. layoutSubviews

  3. drawRect

上面的方法是我们通常自定义一个视图需要重写的方法。但你不必要每个方法都去实现。如果你想要用手势来处理事件,你不需要去重写上面的所有方法。通常,如果你的视图没有包含子视图或者他自己的大小没有改变,那么就没有重写layoutSubview的必要了。最后,当你需要在运行时来修改视图的和你正在使用 UIKit 和 Core Graphics 去绘图时 你可以重写 drawRect 方法是、

window

一个应用程序至少有一个window
window的作用
1.包含可视部分
2.发送事件给你的视图和其他object
3.跟viewcontroller一起工作,加速旋转屏幕的效果

跟Window相关的任务

大多数程序,只有在初始化window时才与window发生交互.然后你可以使用程序窗口来执行一些跟程序相关的任务.

  1. 使用window将点和矩形的块转换到以window坐标系的坐标系统
  2. 使用窗口通知去响应窗口相关改变.

Creating and Configuring a Window(创建和配置window)

我们可以通过 Interface Builder 或者代码去创建Window.不管使用哪种方法,我们需要在启动的时候创建Window.并且我们需要retain window. store a reference 在我们应用程序的代理中UIApplicationDelegate实例. 如果你的程序创建了一个新的Window,使用懒加载(需要的时候再加载).
你必须在创建程序的主window,在程序启动的时候.不管是在前台foreground,还是后台background.当你的程序在后台启动的时候,你需要保证你的window不被显示,直到你的应用程序到前台工作.

Creating window in Interface Builder

xcode项目自动为你做好创建主屏幕的工作.每个项目中都包涵一个Main.storyBoard.除此之外,模板还创建一个outlet,对应程序的主屏幕.你通过outlet去获取主屏幕.

通过Interface builder创建主屏幕是,要在launch option打开 Full Screen.如果你不这样做,你的主屏幕可能比设备的屏幕小,用户动作可能不能被你的视图处理.因为主屏幕接收不到屏幕意外的touch 事件.因为view默认不会被主屏幕裁剪.View可以展现在屏幕上,但是有可能不处理touch事件.将launch option 中对应key 设置为全屏.使得window能适应整个屏幕.

如果你想更新使用Interface builder来创建主屏幕.现在Interface builder拖进一个屏幕window object到你的nib文件中.你还需要做到以下几步.

  1. 想要在运行时获取当前屏幕,你需要将window跟一个outlet关联起来.通常做法是在 应用代理中或者 nib 文件对应的 File owner.
  2. 如果你想要升级,你需要将程序的主nib文件设置为当前的文件.你还必须在 plist中设置 NSMainNibKey的值为你的nib文件名.改变这个值时,你需要确认 nib文件已经被加载并且能被获取到.

Creating a Window Programmatically 代码创建屏幕


代码创建主屏幕,你应该在程序代理的application:didFinishLaunchingWithOptions:方法中创建下面的代码
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

Displaying Content on an External Display

想要显示外置的内容,你需要给你的应用添加额外的window.通过screen object去获取,并展示额外的内容.
通常新的window可以被main Screen获取到.改变windowscreen object致使你屏幕的内容发生响应的改变.只要window可以被当前screen获取到,你就可以像在主屏幕中添加view并展示一样做相同的操作.
UIScreen类拥有一个screen object的列表.代表着可以获取的物理显示.通常,只有一个screen object作为ios应用程序的主显示,但是设备是支持额外显示功能的.所有可以拥有其他的screen.有retina display显示功能的才有额外显示功能.3gs就没有这个功能.

  1. 在应用程序构建时,注册screen 连接和断开通知

  2. 当需要显示的时候,创建并配置一个window

    • 通过UIScreen的screen属性去持有一个screen object,做一些展示额外显示的准备.
    • 创建一个UIWindow实体并配置响应的大小位置.
    • 设置UIScreen object为Window的screen属性.
    • 适配screen object,为了支持你所以要显示的内容.
    • 添加合适的view到UIWindow上.
  3. 显示这个window

你可能感兴趣的:(View Programming Guide For IOS 翻译)