iPhone开发应用之UIView开发流程上篇

移动开发 iOS
不管你是使用系统的视图还是创建自己的视图,你需要理解UIView和UIWindow类所提供的基本结构。这些类提供了复杂的方法来管理视图的布局和展示。

iPhone开发应用中的UIView你了解多少?曾经有人这么说过,在iphone里你看到的,摸到的,都是UIView,所以UIViewiphone开发里具有非常重要的作用。那么UIView我们到底知道多少呢。请看看下面的问题,

如果这些你都知道,那么本文章的内容就请绕道,如果你还不太清楚,我想看了下面的内容,你就明白了。

1、bounds和frame分别表示什么?

2、ContentMode里UIViewContentModeScaleToFill代表什么?

3、contentStretch 里的指定UIView里缩放区域是如何计算的?

4、UIVIew里的哪些属性变化可以用动画来呈现?

5、UIKit的坐标系和Core Graphics的坐标系的差别是什么?
 
视图和窗口展示了应用的用户界面,同时负责界面的交互。UIKit和其他系统框架提供了很多视图,你可以就地使用而几乎不需要修改。当你需要展示的内容与标准视图允许的有很大的差别时,你也可以定义自己的视图

不管你是使用系统的视图还是创建自己的视图,你需要理解UIView和UIWindow类所提供的基本结构。这些类提供了复杂的方法来管理视图的布局和展示。理解这些方法的工作非常重要,使你在应用发生改变时可以确认视图有合适的行为。

视图架构 fundamentals

大部分你想要可视化操作都是由视图对象-即UIView类的实例-来进行的。一个视图对象定义了一个屏幕上的一个矩形区域,同时处理该区域的绘制和触屏事件。一个视图也可以作为其他视图的父视图,同时决定着这些子视图的位置和大小。UIView类做了大量的工作去管理这些内部视图的关系,但是需要的时候你也可以定制默认的行为。

视图与Core Animation层联合起来处理着视图内容的解释和动画过渡。每个UIKit框架里的视图都被一个层对象支持(通常是一个CALayer类的实例),它管理管理着后台的视图存储和处理视图相关的动画。然而,当你需要对视图的解释和动画行为有更多的控制权时,你可以使用层。

为了理解视图和层之间的关系,我们可以借助于一些例子。图1-1显示了ViewTransitions样例程序的视图层次及其对底层Core Animation层的关系。应用中的视图包括了一个window(同时也是一个视图),一个通用的表现得像一个容器视图的UIView对象,一个图像视图,一个控制显示用的工具条,和一个工具条按钮(它本身不是一个视图但是在内部管理着一个视图)。(注意这个应用包含了一个额外的图像视图,它是用来实现动画的)。

为了简化,同时因为这个视图通常是被隐藏的,所以没把它包含在下面的图中。每个视图都有一个相应的层对象,它可以通过视图礶r属性被访问。(因为工具条按钮不是一个视图,你不能直接访问它的层对象。)在它们的层对象之后是Core Animation的解释对象,***是用来管理屏幕上的位的硬件缓存。

iPhone开发应用之UIView开发流程

Figure 1-1 View architecture

使用Core Animation的层对象有很重要的性能意义。一个视图对象的绘制代码需要尽量的少被调用,当它被调用时,其绘制结果会被Core Animation缓存起来并在往后可以被尽可能的重用。重用已经解释过的内容消除了通常需要更新视图的开销昂贵的绘制周期。内容的重用在动画中特别重要,我们可以使用已有的内容,这样比创建新的内容开销更小。

视图层次和子视图管理

除了提供自己的内容之外,一个视图也可以表现得像一个容器。当一个视图包含其他视图时,就在两个视图之间创建了一个父子关系。在这个关系中孩子视图被当作子视图,父视图被当作超视图。创建这样一个关系对应用的可视化和行为都有重要的意义。

在视觉上,子视图隐藏了父视图的内容。如果子视图是完全不透明的,那么子视图所占据的区域就完全的隐藏了父视图的相应区域。如果子视图是部分透明的,那么两个视图在显示在屏幕上之前就混合在一起了。每个父视图都用一个有序的数组存储着它的子视图,存储的顺序会影响到每个子视图的显示效果。如果两个兄弟子视图重叠在一起,后来被加入的那个(或者说是排在子视图数组后面的那个)出现在另一个上面。

父子视图关系也影响着一些视图行为。改变父视图的尺寸会连带着改变子视图的尺寸和位置。在这种情况下,你可以通过合适的配置视图来重定义子视图的尺寸。其他会影响到子视图的改变包括隐藏父视图,改变父视图的alpha值,或者转换父视图。

视图层次的安排也会决定着应用如何去响应事件。在一个具体的视图内部发生的触摸事件通常会被直接发送到该视图去处理。然而,如果该视图没有处理,它会将该事件传递给它的父视图,在响应者链中以此类推。具体视图可能也会传递事件给一个干预响应者对象,像视图控制器。如果没有对象处理这个事件,它最终会到达应用对象,此时通常就被丢弃了。

获取更多关于如何创建视图层次,查看 creating and managing a view hierarchy

视图绘制周期

UIView类使用一个点播绘制模型来展示内容。当一个视图***次出现在屏幕前,系统会要求它绘制自己的内容。在该流程中,系统会创建一个快照,这个快照是出现在屏幕中的视图内容的可见部分。如果你从来没有改变视图的内容,这个视图的绘制代码可能永远不会再被调用。这个快照图像在大部分涉及到视图的操作中被重用。

如果你确实改变了视图内容,也不会直接的重新绘制视图内容。相反,使用setNeedsDisplay或者setNeedsDisplayInRect:方法废止该视图,同时让系统在稍候重画内容。系统等待当前运行循环结束,然后开始绘制操作。这个延迟给了你一个机会来废止多个视图,从你的层次中增加或者删除视图,隐藏,重设大小和重定位视图。所有你做的改变会稍候在同一时间反应。

注意:改变一个视图的几何结构不会自动引起系统重画内容。视图的contentMode属性决定了改变几何结构应该如果解释。大部分内容模式在视图的边界内拉伸或者重定位了已有快照,它不会重新创建一个新的快照。获取更多关于内容模式如果影响视图的绘制周期,查看 content modes

当绘制视图内容的时候到了时,真正的绘制流程会根据视图及其配置改变。系统视图通常会实现私有的绘制方法来解释它们的视图,(那些相同的系统视图经常开发接口,好让你可以用来配置视图的真正表现。)对于定制的UIView子类,你通常可以覆盖drawRect:方法并使用该方法来绘制你的视图内容。也有其他方法来提供视图内容,像直接在底部的层设置内容,但是覆盖drawRect:时最通用的技术

内容模式

视图的内容模式控制着视图如何回收内容来响应视图几何结构的变化,也控制着是否需要回收内容。当一个视图***次显示时,它通常会解释内容,其结果会被底层的层级树捕获为一张位图。在那之后,改变视图的几何结构不会导致重新创建位图。相反,视图中contentMode属性的值决定着这张位图是否该被拉伸,以适应新的边界或者只是简单的被放到角落或者视图的边界。

视图的内容模式在你进行如下操作时被应用:

改变视图frame或者bounds矩形的宽度或者高度时。

赋值给视图的transform属性,新的转换包括一个放缩因子。

大部分视图的contentMode值是UIViewContentModeScaleToFiill,它使视图的内容被放缩到适合新框架的值。Figure 1-2展示了使用其他可用的内容模式的结果。正如你在图中所看到的那样,不是所有的内容模式都可以填充视图的范围,可以的模式可能会扭曲内容。

内容模式很好的支持了视图的内容回收,但是当你想视图在放缩和重设尺寸的操作中重绘你也可以用UIViewContentModeRedraw内容模式。设置这个值绘强制系统调用视图的drawRect:方法来响应几何结构的变化。通常来讲,你应该尽可能的避免使用这个模式,同时你不应该在标准的系统视图中使用这个模式。

获取更多骨干与可用的内容模式,查看UIView Class Reference

iPhone开发应用之UIView开发流程

Figure 1-2

拉伸视图

你可以指定视图的某部分为可拉伸的,以便当视图的尺寸改变时只有可拉伸的部分被影响到。可拉伸的部分通常给按钮或者其他的部分为重复模式的视图。由你指定的可拉伸区域允许沿着两条或者其中一条轴拉伸。当然,当一个视图沿着两条轴拉伸的时候,视图的边界必须也定义了一个重复的模式来避免任何的扭曲。Figure1-3展示了这种扭曲在视图里是怎么表现自己的。每个视图里的原始像素的颜色都自我复制,以便可以填充更大视图的相应区域。

iPhone开发应用之UIView开发流程

Figure 1-3 拉伸一个按钮的背景

你可以用contentStretch属性来定义一个视图的可拉伸区域。这个属性的值一个边的值被标准化为0.0到1.0之间的矩形。当拉伸这个视图时,系统将视图的当前边界值和放缩因子乘以标准值,以便决定哪些像素需要被拉伸。使用标准值可以减轻每次改变视图的边界值都更新contentStretch属性的需要。

视图的内容模式也在决定如何视图的可拉伸区域的使用中扮演着重要的角色。只有当内容模式可能绘引起视图内容放缩的时候可拉伸区域才会被使用。这意味这你的可拉伸视图只被UIViewContentModeScaleToFill, UIViewContentModeScaleAspectFit和UIViewContentModeScaleAspectFill内容模式。如果你指定了一个将内容弹到边界或者角落的内容模式(这样就没有真正的放缩内容),这个视图会忽视可拉伸区域。

注意:当需要创建一个可拉伸UIImage对象作为视图的背景时,使用contentStretch属性是推荐的。可拉伸视图完全被Core Animation层处理,这样性能通常更好。

嵌入式动画支持

使用层对象来支持视图的其中一个利益是你可以轻松的用动画处理视图相关的改变。动画是与用户进行信息交流的一个有用的方法,而且应该总是在进行应用设计的过程中考虑使用动画。UIView类的很多属性是动画化的-也就是,可以半自动的从一个值动画的变化到另一个值。为了实现这样一个动画,你需要做的只是:

1、告诉UIKit你想要实现一个动画

2、改变这个属性的值

在一个UIView对象中有以下的动画化属性:

frame - 你可以使用这个来动画的改变视图的尺寸和位置

bounds - 使用这个可以动画的改变视图的尺寸

center - 使用这个可以动画的改变视图的位置

transform - 使用这个可以翻转或者放缩视图

alpha - 使用这个可以改变视图的透明度

backgroundColor - 使用这个可以改变视图的背景颜色

contentStretch - 使用这个可以改变视图内容如何拉伸

动画的一个很重要的地方是用于从一组视图到另一组视图的过渡。通常来说,会用一个视图控制器来管理关系到用户界面的主要变更的动画。例如,涉及到从高层到底层信息的导航的界面,通常会使用一个导航控制器来管理视图的过渡,这些视图显示了数据的每一个连续层面。然而,你也可以使用动画来创建两组视图的过渡,而不是视图控制器。当你想用一个系统提供的视图控制器无法支持的导航方案时你可能会这样做。

除了用UIKit类可以创建动画外,你也可以用Core Animation层来创建动画。在更低层你有更多的在时间或者动画属性上的控制权。

获取更多关于如何创建一个基于视图的动画,查看 Animations

获取更多关于使用Core Animation创建动画的信息,查看Core Animation Programming Guide和Core Animation Cookbook.

视图几何结构和坐标系统

UIKit的默认坐标系统把原点设置在左上角,两条轴往下和右扩展。做标志被表示为浮点数,这样允许内容的精确布局和定位而不管底层的屏幕。Figure1-4展示了相对于屏幕的坐标系统。除了屏幕坐标系统窗口和视图也定义了它们自己的本地坐标系统,这样允许你指定相对于视图或者窗口原点的坐标而不是屏幕。

 

iPhone开发应用之UIView开发流程

Figure 1-4 UIKit中的坐标系统

因为每个视图和窗口都定义了它自己的本地坐标系统,你需要留意在任何时间内是哪个坐标系统在起作用。每次绘制或者改变一个视图都是基于一个坐标系统的。在某些绘制中会基于视图本身的坐标系统。在某些几何结构变更中是基于父视图的坐标系统的。UIWindow和UIView类都包含了帮助你从一个坐标系统转换到另一个的方法。

重要:一些iOS技术定义了默认的坐标系统,它们的原点和方向与UIKit的不同。;例如,Core Graphics和OpenGL ES的坐标系统是原点在可视区域的左下角,而y轴往上递增。当绘制或者创建内容时,你的代码应该考虑到一些不同并且适应坐标值。

frame, bounds和center属性之间的关系

视图对象使用frame, bounds和center属性来跟踪它的尺寸和位置:

frame属性包含了frame矩形,指定了在父视图坐标系统中该视图的尺寸和位置。

center属性包含了在父视图坐标系统中的已知中心点。

bounds属性包含了边界矩形,指定了在视图本地坐标系统中视图的尺寸。

主要使用center和frame属性来控制当前视图的几何结构。例如,当在运行时构建你的视图层次或者改变视图的尺寸或者位置时你可以使用这些属性。如果你只是要改变视图的位置,那么推荐使用center属性。center属性的值永远是可用的,即使添加了放缩或者转换因子到视图的转换矩阵当中。但是对于frame属性却不是,当视图的转换矩形不等于原始矩阵时它被当作时无效的。

在绘制的过程中主要使用bounds属性。这个边界矩阵在视图的本地坐标系统被解释。这个矩形的默认原点是(0, 0),它的尺寸也适应frame矩形的尺寸。任何绘制在这个矩形当中的东西都是该视图的可视内容的一部分。如果你改变了bounds矩形的原点,任何你绘制在新矩形的东西都会变成该视图可视内容的一部分。

Figure1-5展示了一个图像视图的frame和bounds矩形之间的关系。图中,图像视图的右上角被定位在父视图坐标系统的(40, 40),它的矩形尺寸为240x380。对于bounds矩形,原点是(0, 0),矩形尺寸也是240x380。

 

iPhone开发应用之UIView开发流程

Figure 1-5 视图frame和bounds之间的关系

即使你可以独立的改变frame,bounds和center属性,其中一个改变还是会影响到另外两个属性:

当你设置了frame属性,bounds属性的尺寸值也改变来适应frame矩形的新尺寸。center属性也会改变为新frame矩形的中心值。

当你设置了center属性,frame的原点也会相应的改变。

当你设置了bounds属性,frame属性会改变以适应bounds矩形的新尺寸。

视图的框架默认不会被它的父视图框架裁剪。这样的化,任何放置在父视图外的子视图都会被完整的解释。你可以改变这种行为,改变父视图的clipsToBounds属性就可以。不管子视图是否在视觉上被裁剪,触屏事件总是发生在目标视图父视图的bounds矩形。换句话说,如果触摸位于父视图外的那部分视图,那么该事件不会被发送到该视图。

小结:关于iPhone开发应用之UIView开发流程 上篇的内容介绍完了,如果你对本文感兴趣的话,请继续阅读 iPhone开发应用之UIView开发流程 下篇,***希望本文能对你有所帮助!关于iphone开发的更多内容,请去iphone开发频道

责任编辑:zhaolei 来源: 博客园
相关推荐

2011-08-11 10:27:37

iPhoneUIView视图

2011-08-12 11:31:46

iPhoneUIView动画

2011-07-19 09:46:38

2011-08-15 13:50:06

IPhone开发UIView动画

2011-08-16 19:02:23

iPhone开发绘图

2011-08-10 10:23:20

iPhoneArchivingNSCoder

2011-08-04 16:17:39

iPhone 开发工具

2011-08-15 10:35:43

iPhone开发Atomicnonatomic

2011-08-15 18:02:32

iPhone开发表视图

2011-08-15 10:15:00

iPhone开发警告框

2011-08-11 11:51:07

iPhone键盘

2011-08-19 14:27:29

iPhone开发

2011-08-22 14:21:24

iPhone开发UIView Anim

2011-08-05 13:49:53

iPhone 应用 开发

2011-08-11 17:32:51

iPhone视图

2011-08-16 18:13:42

IPhone开发UIView动画

2011-08-12 10:16:10

iPhone通讯录联系人

2011-06-28 10:23:27

UIViewiOS

2011-07-19 09:58:36

2011-07-08 14:58:16

iPhone Xcode iOS
点赞
收藏

51CTO技术栈公众号