UIView简介


作用

A view is an object that draws itself within a rectangular area of a window and that can respond to user actions such as finger taps or mouse clicks. A view draws a visual representation of itself and presents a surface that responds to touches and input from devices. Not all views handle events, but views are more likely to handle events than other types of responder objects (that is, objects capable of responding to events). Views also provide the content for printing. For a view to be useful, it must be situated in the view hierarchy of a window.

视图是UIView类的实例,负责在屏幕上定义一个矩形区域。在iPhone的应用程序中,视图在展示用户界面及响应用户界面交互方面发挥关键作用。每个视图对象都要负责渲染视图矩形区域中的内容,并响应该区域中发生的触碰事件。这一双重行为意味着视图是应用程序与用户交互的重要机制。在一个基于模型-视图-控制器的应用程序中,视图对象明显属于视图部分。

除了显示内容和处理事件之外,视图还可以用于管理一或多个子视图。子视图是指嵌入到另一视图对象边框内部的视图对象,而被嵌入的视图则被称为父视图或超视图。视图的这种布局方式被称为视图层次,一个视图可以包含任意数量的子视图,通过为子视图添加子视图的方式,视图可以实现任意深度的嵌套。视图在视图层次中的组织方式决定了在屏幕上显示的内容,原因是子视图总是被显示在其父视图的上方;这个组织方法还决定了视图如何响应事件和变化。每个父视图都负责管理其直接的子视图,即根据需要调整它们的位置和尺寸,以及响应它们没有处理的事件。

创建一个视图对象

创建视图对象的最简单方法是使用Interface Builder进行制作,然后将视图对象从作成的nib文件载入内存。在Interface Builder的图形环境中,您可以将新的视图从库中拖出,然后放到窗口或另一个视图中,以快速建立需要的视图层次。Interface Builder使用的是活的视图对象,因此,当您用这个图形环境构建用户界面时,所看到的就是运行时装载的外观,而且不需要为视图层次中的每个视图编写单调乏味的内存分配和初始化代码。

如果您不喜欢Interface Builder和nib文件,也可以通过代码来创建视图。创建一个新的视图对象时,需要为其分配内存,并向该对象发送一个initWithFrame:消息,以对其进行初始化。举例来说,如果您要创建一个新的UIView类的实例作为其它视图的容器,则可以使用下面的代码:

//在视图初始化时指定的边框矩形代表该视图相对于未来父视图的位置和大小。在将视图显示于屏幕上之前,您需要将它加入到窗口或其它视图中。在这个时候,UIKit会根据您指定的边框矩形将视图放置到其父视图的相应位置中。
CGRect  viewRect = CGRectMake(0, 0, 100, 100);
UIView* myView = [[UIView alloc] initWithFrame:viewRect];

添加和移除子视图

Interface Builder是建立视图层次的最便利工具,因为它可以让您看到视图在运行时的外观。在界面制作完成后,它将视图对象及其层次关系保存在nib文件中。在运行时,系统会按照nib文件的内容为应用程序重新创建那些对象和关系。当一个nib文件被装载时,系统会自动调用重建视图层次所需要的UIView方法。

如果您不喜欢通过Interface Builder和nib文件来创建视图层次,则可以通过代码来创建。如果一个视图必须具有某些子视图才能工作,则应该在其initWithFrame:方法中进行对其创建,以确保子视图可以和视图一起被显示和初始化。如果子视图是应用程序设计的一部分(而不是视图工作必需的),则应该在视图的初始化代码之外进行创建。在iPhone程序中,有两个地方最常用于创建视图和子视图,它们是应用程序委托对象的applicationDidFinishLaunching:方法和视图控制器的loadView方法。

可以通过下面的方法来操作视图层次中的视图对象:

  1. 调用父视图的addSubview:方法来添加视图,该方法将一个视图添加到子视图列表的最后。
  2. 调用父视图的insertSubview:...方法可以在父视图的子视图列表中间插入视图。
  3. 调用父视图的bringSubviewToFront:、sendSubviewToBack:、或exchangeSubviewAtIndex:withSubviewAtIndex:方法可以对父视图的子视图进行重新排序。使用这些方法比从父视图中移除子视图并再次插入要快一些。
  4. 调用子视图(而不是父视图)的removeFromSuperview方法可以将子视图从父视图中移除。

在添加子视图时,UIKit会根据子视图的当前边框矩形确定其在父视图中的初始位置。可以随时通过修改子视图的frame属性声明来改变其位置。缺省情况下,边框位于父视图可视边界外部的子视图不会被裁剪。如果希望激活裁剪功能,必须将父视图的clipsToBounds属性设置为YES。

重要提示 :在内存管理方面,可以将子视图考虑为其它的集合对象。特别是当您通过addSubview:方法将一个视图作为子视图插入时,父视图会对其进行保持操作。反过来,当您通过removeFromSuperview方法将子视图从父视图移走时,子视图会被自动释放。在将视图加入视图层次之后释放该对象可以避免多余的保持操作,从而避免内存泄露。

当为某个视图添加子视图时,UIKit会向相应的父子视图发送几个消息,通知它们当前发生的状态变化。可以在自己的定制视图中对诸如willMoveToSuperview:、willMoveToWindow:、willRemoveSubview:、didAddSubview:、didMoveToSuperview、和didMoveToWindow这样的方法进行重载,以便在事件发生的前后进行必要的处理,并根据发生的变化更新视图的状态信息。

在视图层次建立之后,可以通过视图的superview属性来取得其父视图,或者通过subviews属性取得视图的子视图。也可以通过isDescendantOfView:方法来判定一个视图是否在其父视图的视图层中。一个视图层次的根视图没有父视图,因此其superview属性被设置为nil。对于当前被显示在屏幕上的视图,窗口对象通常是整个视图层次的根视图。

也可以通过视图的window属性来取得指向其父窗口(如果有的话)的指针,如果视图还没有被链接到窗口上,则该属性会被设置为nil。

实现视图动画

动画为用户界面在不同状态之间的迁移过程提供流畅的视觉效果。在iPhone OS中,动画被广泛用于视图的位置调整、尺寸变化、甚至是alpha值的变化(以实现淡入淡出的效果)。动画支持对于制作易于使用的应用程序是至关重要的,因此,UIKit直接将它集成到UIView类中,以简化动画的创建过程。

UIView类定义了几个内在支持动画的属性声明—也就是说,当这些属性值发生变化时,视图为其变化过程提供内建的动画支持。虽然执行动画所需要的工作由UIView类自动完成,但您仍然必须在希望执行动画时通知视图。为此,您需要将改变给定属性的代码包装在一个动画块中。

动画块从调用UIView的beginAnimations:context:类方法开始,而以调用commitAnimations类方法作为结束。在这两个调用之间,您可以配置动画的参数和改变希望实行动画的属性值。一旦调用commitAnimations方法,UIKit就会开始执行动画,即把给定属性从当前值到新值的变化过程用动画表现出来。动画块可以被嵌套,但是在最外层的动画块提交之前,被嵌套的动画不会被执行。

列举了UIView类中支持动画的属性:

属性 描述
frame 视图的边框矩形,位于父视图的坐标系中。
bounds 视图的边界矩形,位于视图的坐标系中。
center 边框的中心,位于父视图的坐标系中。
transform 视图上的转换矩阵,相对于视图边界的中心。
alpha 视图的alpha值,用于确定视图的透明度。

响应事件

UIView类是UIResponder的一个子类,因此能够接收用户和视图内容交互时产生的触摸事件。触摸事件从发生触摸的视图开始,沿着响应者链进行传递,直到最后被处理。视图本身就是响应者,是响应者链的参与者,因此可以收到所有关联子视图派发给它们的触摸事件。

处理触摸事件的视图通常需要实现下面的所有方法,更多细节请参见“事件处理”部分:

touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:

请记住,在缺省情况下,视图每次只响应一个触摸动作。如果用户将第二个手指放在屏幕上,系统会忽略该触摸事件,而不会将它报告给视图对象。如果您希望在视图的事件处理器方法中跟踪多点触摸手势,则需要重新激活多点触摸事件,具体方法是将视图的multipleTouchEnabled属性声明设置为YES。

某些视图,比如标签和图像视图,在初始状态下完全禁止事件处理。您可以通过改变视图的userInteractionEnabled属性值来控制视图是否可以对事件进行处理。当某个耗时很长的操作被挂起时,您可以暂时将这个属性设置为NO,使用户无法对视图的内容进行操作。为了阻止事件到达您的视图,还可以使用UIApplication对象的beginIgnoringInteractionEvents和endIgnoringInteractionEvents方法。这些方法影响的是整个应用程序的事件分发,而不仅仅是某个视图。

在处理触摸事件时,UIKit会通过UIView的hitTest:withEvent:和pointInside:withEvent:方法来确定触摸事件是否发生在指定的视图上。虽然很少需要重载这些方法,但是您可以通过重载来使子视图无法处理触摸事件。

视图对象的清理

如果您的视图类分配了任何内存、存储了任何对象的引用、或者持有在释放视图时也需要被释放的资源,则必须实现其dealloc方法。当您的视图对象的保持数为零、且视图本身即将被解除分配时,系统会调用其dealloc方法。您在这个方法的实现中应该释放视图持有的对象和资源,然后调用超类的实现。

- (void)dealloc {
    // Release a retained UIColor object
    [color release];

    // Call the inherited implementation
    [super dealloc];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值