View Programming Guide for iOS 学习笔记_2

这几天刚回学校,事情比较多,对文档的翻译进度慢了一些,最近我在想要不要把我写的这些东西放在github上,但是我还不太会用,等几天学学怎么用然后把这些东西放在github上好了。

今天学习到如何写注释的方法,注释应该是注释接下来的代码是干什么的,把这一段代码的实现的功能写下来,而不是对每一条语句进行说明。

Views

因为view对象是用户与你的应用程序交互的主要途径,所以view有许多职责。下面是其中的一些职责

  • 布局和管理子视图
    • 一个view定义自己默认的重新调整大小的行为(这些大小调整行为是与它的父视图相关的)
    • 一个view可以管理子视图(们)
    • 一个视图可以覆盖它的子视图的大小和位置。
    • 一个view可以把一个点从自己的坐标系转换到其他view或window的坐标系
  • 绘制和动画
    • 一个view在自己的矩形区域内绘制内容
    • 一些view属性可以用动画来显示新值
  • 事件处理
    • 一个view可以接受触摸事件
    • 一个视图是处理响应链里的(responder chain)

这些章节着重于创建、管理、绘制view和处理布局、管理视图层次结构的步骤上。(For information about how to handle touch events (and other events) in your views, see Event Handling Guide for iOS.)

创建和配置一个view视图

你可以通过代码或者Interface Builder来创建view(们),随后你把他们装配到视图层次结构里以供使用。

使用Interface Builder创建视图对象

创建一个view最简单的方式是通过Interface Builder来图像化的装配他们。在Interface Builder里,你可以添加view(们)到你的界面、将这些view(们)整理到一个层次结构、配置每一个视图的设置、将与view相关的行为与你的代码连接起来。因为在Interface Builder中的view是实时视图对象,所以你设计的view对象是什么样的最终运行的时候看见的就是什么样的。随后你把这些实时对象保存到一个nib文件,nib文件是一个保存你创建对象状态和配置的资源文件。

通常你使用nib文件来为你应用程序的view controller保存一个完整的视图层次结构。nib文件的最顶层通常包含一个单独的view对象,这个view对象表示你的view controller的view(通常view controller对象是被File‘s owner对象所表示的)。这个顶层的view应该被调整的适合目标设备,并且包含所有其他的用来被显示的view(们)。只用nib文件保存view controller的view的一部分会是很少见的。

当nib文件与view controller一起使用时,你所需要做的全部事情就是用nib文件的信息来初始化这个view controller。这个view controller在合适的时间加载或者卸载你的view(们)。然而,如果你的nib文件没有与一个view controller相关联,你通常可以用一个NSBundle对象或UINib对象加载这个nib文件的内容,这些NSBundle和UINib对象用nib文件中的数据去重建你的view对象。

更多怎么使用Interface Builder创建和配置view的信息,请查看Interface Builder User Guide. 更多关于view controller怎么加载和管理与之相关的nib文件的信息,请查看View Controller Programming Guide for iOS中的Creating Custom Content View Controllers . 更多关于怎样用代码从一个nib文件中加载视图,查看 Resource Programming Guide中的Nib File。

使用代码创建view对象

如果你更喜欢使用代码创建view,你可以使用标准的allocation/initialization模型。view默认的初始化方法是initWithFrame:方法,这个方法初始化了view在父视图下的位置和大小。比如,为了创建一个普通的UIView对象,你应该使用类似于类似于下面的代码:

CGRect viewRect = CGRectMake(0, 0, 100, 100);

UIView *myView = [[UIView alloc]initWithFrame:viewFrame];

注意尽管所有的view都支持initWithFrame方法,一些view可能有更好的你应该使用的初始化方法。更多关于初始化方法的使用习惯,查看相应的class的reference documentation。

当你创建了一个view之后,你必须在它被显示的之前把它添加到一个window或window里的另一个view里。更多关于如何将view添加到视图层次结构的信息,请查看Adding and Removing Subviews.

设置视图的属性

UIView类有几个声明属性控制视图的外观和行为。这些属性是为了操作view的位置和大小,view的透明度,背景颜色,和view的渲染行为。所有这些属性都有合适的默认值,这个值是你可以随后在需要的时候改变的。你同样可以使用Interface的Inspector窗口来配置这些的属性。

表3-1列出了一些常用的属性和方法并描述了他们的用法,相关的属性被列到了一起,这样你就可以看到影响视图的某些方面的选项。

表3-1

propertyusage
alpah,hidden,opaque这些属性影响view的不透明性。alpha和hidden直接改变视图的不透明性。opaque属性诉系统该如何组合你的view。当你的view的内容是完全不透明时把opaque属性设置为YES,这样在这个view内容直线的所有东西都不会显示。把这个属性设置为YES通过排除不必要的这操作来来提高性能。
bounds,frame,center,transform这些属性影响view的大小和位置。center和frame属性是表现这个view位置(在父视图坐标系下)。frame属性包含view的大小。bounds属性定义了view的可见内容区域(在自己的坐标系下)。transform属性用来以复杂的方式显示动画或移动整个view。比如,你会使用transform去旋转或缩放一个view。如果当前的transform不是恒等变化,frame属性就是未定义的并且应该被忽略。详见The Relationship of the Frame, Bounds, and Center Properties和 Coordinate System Transformations.
autoresizingMask,autoresizesSubviews这些属性影响自动调整view和view子视图大小的行为。autoresizingMask属性控制一个view如何在它的父视图边界内相应改变。autoresizesSubviews属性控制究竟当前view的子视图是否被重新改变大小。
contentMode,contentStretch,contentScaleFactor这些属性影响view内的content的渲染行为。contentMode属性和contentStretch属性决定当视图的宽度或高度改变时,view的content该如何改变。contentScaleFactor属性只在你需要为高分辨率的屏幕自定义view的绘制行为时使用。更多相关内容,详见contentMode,Stretch Views。更多关于如何操作scale factor的信息,详见Drawing and Printing Guide for iOS的Supporting High-Resolution Screens In Views .
gestureRecognizers,userInteractionEnabled,multipleTouchEnabled,exclusiveTouch这些属性影响你的view如何处理触摸事件。gestureRecognizer属性包含依附在该view上的手势识别。其他的几个属性控制view支出的触摸事件。更多如何在你的view里相应事件的信息,详见Event Handling Guide for iOS.
backgroundColor,subviews,drawRect:方法,layer,(layerClass方法)这些属性和方法帮助你管理你view的实际内容。对于简单的view,你可以设置一个背景颜色并加入一个或多个view。subviews属性包含一个只读的子视图列表,但是有很多添加和重新整理subviews的方法。对于包含自定义绘制行为的view,你必须覆盖drawRect:方法。对于更高级的内容,你可以直接在视图的Core Animation层工作。为了为view指定一个完全不同类型的层,你必须覆盖layerClass方法。

对于更多所有view都有的基本属性,你可以通过UIView Class Reference 查看。

为将来的识别为view添加标签

UIView类包含一个标签属性,你可以使用这个tag属性给view用一个整数添加一个标签。你可以用标签来唯一的确定你视图层次结构中的view并且在运行时执行对这些view的搜索(基于标签的搜索比你自己遍历视图层次结构要快)。tag属性默认值为0。
为搜索一个被打上标签的view,使用UIView的viewWithTag:方法。这个方法为接受对象和它的子视图执行深度优先搜索。这个方法将不会搜索父视图或者这个视图层次结构中的其他部分。因此从根视图调用这个方法会搜索所有在这个视图层次结构中的view,但是在一个特定的子视图调用这个方法只会搜索view的一个子集。

创建和管理视图层次结构

管理视图层次结构是开发你应用程序用户界面的一个重要部分。view的组织不仅在影响应用程序的视觉表现,而且影响你的应用程序如何去相应改变和事件。比如说,在视图层次结构中的父子关系决定了哪一个对象会处理特殊的触摸事件。类似的,视图层次结构中的父子关系也视图决定了视图如何相应界面方向的改变。

添加和移除子视图

使用Interface Builder是创建一个视图层次结构最方便的方法,因为你可以图形化的组装你的view,查看view之间的关系,查看在运行时这些view是如何显示的。当使用Interface Builder时,你保存你的视图层次结构到一个nib文件,当在运行时需要这个视图时这个文件将会被加载。

如果你更喜欢使用代码创建你的view,你创建并初始化view后应该使用下面的方法把他们添加到视图层次结构中。

  • 将一个子视图添加到父视图中,调用父视图的addSubview:方法。这个方法将这个子视图添加到父视图的子视图列表中
  • 将一个子视图插入到父视图的子视图列表的中间去,调用父视图的insertSubview:方法。讲一个子视图插入到列表的中间在视觉上把这个view放置在任何后加入这个列表的view之后。
  • 为了重新排列父视图已有的子视图,调用父视图的bringSubviewToFront:sendSubviewToBack:或者exchangeSubviewAtIndex:withSubviewAtIndex:方法。使用这些方法比移除view再插入view要来的快。
  • 为了从父视图移除一个子视图,调用子视图removeFromSuperview方法。

当添加一个子视图到它的父视图时,这个子视图的当前frame矩形表示它在它的福斯图当中的起始位置。一个超出父视图可见边界的子视图将不会默认被剪切。如果你想要你的子视图被父视图的边界剪切,你应该显式的把子视图的clipsToBounds属性设置为YES。

一个你可能添加子视图到视图层次结构的地方就是在view controller的loadView:ViewDidLoad:方法中。如果你用代码创建你的视图,你应该把view的创建代码写在view controller的loadview:方法中。无论你使用代码创建你的view或是从一个nib文件中加载他们,你可以在viewDidLoad:方法中增加额外的view配置代码。

重要父视图会自动的retain子视图,所以当嵌入一个子视图之后的安全做法是release这个子视图。事实上,这样做是苹果公司推荐的,因为这种做法保护你的应用程序免受内存泄露的困扰(过多的retain该视图)。只要记住如果你把一个子视图从它的父视图中移除了,并且想要重用它的时候,你应该再次retain这个子视图。removeFromSuperview方法会在从父视图中已吃一个子视图之前autorelease该子视图。如果你不在下一个事件循环之前retain这个view,这个视图将会被release。更多关于Cocoa内存管理习惯的信息,详见Advanced Memory Management Programming Guide.

当你把一个子视图添加到另一个视图,UIKit会就这个变化同时通知父视图和子视图。如果你实现了自定义视图,你可以通过覆盖 willMoveToSuperview:, willMoveToWindow:, willRemoveSubview:, didAddSubview:, didMoveToSuperview, didMoveToWindow: 方法中的一个或多个来拦截这些通知。你可以使用这些通知去更新任何与你视图层次结构相关的状态信息或执行额外的任务。

在创建了一个视图层次结构之后,你可以使用view的superview和subviews属性来导航。每一个view的window属性包含view当前是在哪个window显示的。因为视图层次结构中的根视图没有父视图,所以他的superview属性被设置为nil。对于当前在屏幕上显示的view,屏幕的window对象就是视图层次结构的根视图。

隐藏视图

为了在视觉上隐藏一个视图,你可以把视图的hidden属性设置为YES,或着把它的alpha值设置为0.0。隐藏的视图不会接收系统的触摸事件。然而,隐藏视图会参与到重新调整大小操作和与视图层次结构相关的其他布局操作。因此,通常隐藏一个视图是把一个view从你的视图层次结构中移除的边界选择,尤其是你计划在不久之后重新显示这个视图。

重要如果你把一个现在是第一响应者的view隐藏了,这个view不会自动的放弃他的第一响应者状态。把这个第一响应者作为目标的事件仍然会被传送到这个隐藏的view。为了防止这种事件的发生,当你隐藏一个视图时你应该强制你的view放弃它的第一响应者状态。更多关于响应者链的信息,请查看Event Handling Guide for iOS。

如果你想要用动画显示一个view从可见到隐藏的过渡,你必须使用view的alpha属性。这个hidden属性不是一个有动画的属性,所以任何你对它做的改变都会立即生效。

在一个视图层次结构中定位一个view

有两种在视图层次结构中定位一个view的方法。

  • 把任何相关视图的指针存储在一个适当的位置,比如在拥有这个视图的view controller中。
  • 为每一个view的tag属性添加一个唯一的整数,并使用viewWithTag:方法来定位它。

储存相关视图的引用是最常用的定位一个view的放啊,这使得访问这些view变得方便。如果你使用Interface Builder创建了你的view,你可以使用outlet把你的nib文件中的对象连接到另一个对象。对于你用代码创建的view,你可以使用私有成员变量来储存这些view的引用。无论你使用outlet还是私有成员变量,你有责任在有需要的时候去retain这个view,release这个view。保证对象被正确的retain和release的最好方法是使用declared properties。

Tags是一个减少硬编码的依赖性并提供更多动态和灵活的解决方法的很有用的方式。相对储存一个view的引用,你可以通过view的tag来定位这个view。tag同时也是引用一个view更持久的方法。比如说,如果你想要保存一个现在在你的应用程序中可见view的一个list,你会在一个文件中写下每一个可见view的tag。这比归档这个实际的view对象要简单,尤其是在当你只是在跟踪哪一个view是现在被显示的情况下。当你的应用程序随后被加载时,你会再次重新创建view并使用保存的tag的list来设置每一个view,并由此使视图层次结构返回之前的状态。

位移,缩放和旋转view

每一个view都有一个相关的affine transform(仿射变换),你可以用这个affine transform来位移,缩放或旋转这个view的的内容。view变换改变这个view最终渲染内容的表现并且经常被用来事件滚动,动画和其他视觉效果。

UIView的transform属性包含一个来使view产生改变CGAffineTransform结构。默认情况下,这个属性是被设置为恒等变换的,恒等变化不会改变view的表现。你可以随时把一个新的改变指派给这个属性。比如,为了让一个view按45°来旋转,你可以使用如下的代码:

CGAffineTransform xForm = CGAffineTransformMakeRotation(M_PI / 4.0);
self.view.transform = xForm;

当吧多种改变应用到一个view上时,加入这些改变到CGAffineTransform结构的顺序是很长中交的。旋转这个view,然后再位移与先位移再旋转的效果是不同的。即使旋转和位移的量都是完全相同的,变化的顺心也会影响到最终的结果。所有你对一个view做的变化都是与中心点相关联的。因此,应用一个旋转因子到view上,这个视图会围绕中心点做旋转。缩放一个视图改变视图的宽度和高度当不改变中心点。

更多关于创建和使用affine transform的信息,请查看Quartz 2D Programming Guide中的transform。

在视图层次结构中转换坐标

在多种情况下,尤其是在处理事件的情况先,应用程序可能需要从一个参照系坐标值转换到另一个。比如,触摸事件会报告每一个触摸事件的位置,这个位置是在window坐标下的,但是试图对象经常需要的是这个位置在自己坐标系下的值。UIView类为转换一个坐标到自己的坐标系和从自己的坐标系转换一个坐标定义了如下的方法 :

  • covertPoint: FromView:
  • convertRect: FromView:
  • convertPoint: toView:
  • convertRect: toView:

covertPoint: FromView:方法吧把一个坐标从其他view的坐标系下转化到当前view自己的坐标系下(bounds 矩形)。相反的,convertPoint: toView:方法把一个坐标从当前view的坐标系下转换到其他指定的坐标系下。如果你把上述方法中的设计到view设置为nil的话,那么坐标就是从包含当前view的window坐标系下转换到当前view坐标系下,或从当前view坐标系下转换到包含当前view的window坐标系下。

除了UIView的转换方法,UIWindow类也定义了一些转换的方法。这些方法与UIView的方法的版本类似,只是把转换到当前view的坐标下和从当前view的坐标下转换改成了转换到window的坐标系下和从window的坐标系下转换。

  • convertPoint: fromWindow:
  • convertRect: fromWindow
  • convertPoint: toWindow
  • convertRect: toWindow

当在转换已旋转的view的坐标值时,UIKit转换矩形 ???

在运行时调整视图的大小和位置

无论何时一个view的大小和位置发生了变化,这个视图的子视图的大小和位子也要相应的发生变化。UIView类同时提供自动和手动调整view布局的方式。当采用自动布局时,你需要设置每一个view在其父视图大小改变时需要遵守的规则,然后完全忘记重新调整的操作。当采用手动布局时,在有需要时你要手动调整view的大小。

为布局改变做好准备

任何时候,一个view里任何以下的事件发生都可能会导致布局改变。

  • view的bounds矩形的size发生变化。
  • 界面方向有改变发生,这通常会导致根视图的bounds矩形发生改变。
  • 与view的层相关的Core Animation子层集发生改变并需要布局。
  • 应用程序通过调用setNeedsLayout:layoutIfNeed方法强制布局。
  • 应用程序通过调用view之下的layer对象的setNeedsLayout:方法来强制布局。
使用自动调整大小规则来自动的处理布局改变

当你改变view的size时,内嵌的任何子视图的大小和位置通常需要改变来适应它的父视图新的size。子视图的autoresizesSubviews属性决定了子视图是否需要重新调整大小。如果这个属性被设置为YES,这个view使用每一个子视图的autoresizingMask属性来决定如何子视图如何调整大小和位置。任何子视图size的改变触发同样子视图的子视图的布局调整。
对在视图层次结构中的每一个view,设置这个view的autoresizingMask属性为一个合适的值是处理自动布局改变的一个重要部分。表3-2列出了你可以赋给你view自动调整的选项,并描述了在布局操作发生的时候它们产生的效果。你可以使用或运算符来把这些常量联合起来,或是在把他们赋给autoresizingMask属性之前把他们加到一起。如果你是使用的Interface Builder来装配你的view的,是应该使用Autosizing检视器来设置这些属性。

Autoresizing mask描述
UIViewAutoresizingNone这个view不自动调整size(默认值)
UIViewAutoresizingFlexibleHeight当view的父视图的高度发生改变时该view的的高度也变化。如果不包含这个常量,这个view的高度不会变化
UIViewAutoresizingFlexibleWidth当父视图的宽度发生改变时,这个view的宽度发生改变。如果不包含这个常量,这个view的宽度不会改变
UIViewAutoresizingFlexibleLeftMargin视图的左边界和父视图的左边界的距离在需要时增大或缩小。如果不包含这个属性,这个view的左边界和父视图左边界的距离就是一个定值
UIViewAutoresizingFlexibleRightMargin视图的右边界和父视图的右边界的距离在需要时增大或缩小。如果不包含这个属性,这个view的右边界和父视图右边界的距离就是一个定值
UIViewAutoresizingFlexibleBottomMargin视图的底边界和父视图的底边界的距离在需要时增大或缩小。如果不包含这个属性,这个view的底边界和父视图底边界的距离就是一个定值
UIViewAutoresizingFlexibleTopMargin视图的顶边界和父视图的顶边界的距离在需要时增大或缩小。如果不包含这个属性,这个view的顶边界和父视图顶边界的距离就是一个定值

最简单的配置autoresizing规则的方法就是使用Interface Builder的size检视器的 Autosizing控制。

重要如果view的transform属性不包含恒等变换,view的frame就是未定义的,view的autoresizing的行为也是未定义。
当所有的受影响的view的autoresizing规则都被应用之后,UIKit 返回并给每一个view机会去做一些必须的相对于view父视图的手工调整。更多关于如何手动管理view的布局,详见Tweaking the Layout of Your Views Manually。

手动微调view的布局

当一个view的size发生变化时,UIKit应用view子视图的的autoresizing行为然后调用view的layoutSubviews方法来做一些手动的调整。在自定义的视图中,如果view自己的autoresizing行为不能满足你的需求,你可以可以实现layoutSubviews方法来做一些调整。你自己对这个方法的实现可以做如下的事情:

  • 调整任何直接子视图的大小和位置。
  • 添加、移除子视图或Core Animation层。
  • 通过调用子视图的setNeedsDisplysetNeedsDisplayInRect方法强制一个子视图重绘

应用程序经常手动对子视图布局的地方是在实现一个大的可滚动区域时。因为可滚动内容有一个单独的大的view是不现实的,应用程序通常实现一个包含很多小瓷片视图的根视图。每一个瓷片表示这个可滚动内容的一部分。当一个滚动事件发生时,这个根视图调用他自己的setNeedsLayout方法去吃书画一个布局改变。它的layoutSubviews方法随后基于滚动发生的量来重调瓷片view的位置。一旦cipianview滚出了view的可见区域,layoutSubviews方法移动这个瓷片view到即将到到的边缘,代替他们的内容。
当写你的布局代码时,一定要用如下的方式测试你的code:
* 改变view的方向来保证这个布局在所有的界面朝向都是正确的。
* 确保你的代码在状态栏高度的变化作出适当的响应。当一个电话active时,这个状态栏的高度会增加,当用户挂断电话时,状态栏的高度减小。

更多关于自动调整行为如何影响到view的大小和位置,查看 Handling Layout Changes Automatically Using Autoresizing Rules。

在运行时修改视图

应用程序从用户那里接收输入,然后调整用户界面区域相应用户的输入。应用程序可能通过重新整理、改变view的大小和位置、显示或隐藏、加载一个全新的视图集来对view进行改变。有执行这些动作的许多地方和方法:

  • 在一个view controller里
    • view controller必须在显示视图之前创建它们。可以从nib文件中加载这些视图也可以用代码创建。当这些view不再被需要时,view controller清楚它们。
    • 当一个设备改变了方向,view controller可能调整视图的大小和位置来适应设备方向的改变。作为适应新设备方向的一部分,view controller可能会隐藏一些视图并显示某些视图。
      *当一个view controller管理可编辑的内容,在进入编辑模式或进入编辑模式时,view controller可能会调整view controller的视图层次结构。
  • 在动画block中
    • 在你的用户界面中,当你想要在两个视图集之间过渡时,在动画block中你会隐藏某些视图并显示某些视图
    • 当实现特殊的效果时,你可能会使用一个动画block去修改view的大量属性。eg.为了使用动画改变view的size,你会改变view的frame矩形的size。
  • 其他方式
    *当触摸事件或手势事件发生时,你的界面可能会通过加载新的view集火改变现有的view集来相应这些时间。更多关于处理事件,请查看Event Handling Guide for iOS.
    • 当用户与一个滚动视图交互时,一个大的可滚动的区域可能会隐藏起来并且显示瓷片子视图。更多管局支持可滚动内容的信息,请查看Scroll View Programming Guide for iOS.
      *当一个键盘显示时,你可能会重新改变视图的大小和方向,这样他们就不会在键盘下被遮盖住。更多关于如何与键盘交互的信息,请查看Text Programming Guide for iOS。

view controller是对view初始化改变的常用的场所。因为view controller管理与显示内容相关的视图层次结构,view controller是相应发生在视图上的所有事情最终的地方。当加载view controller的视图或者处理界面方向改编时,view controller可以增加视图,隐藏或替代某一个视图,并且做一系列的改变来使视图做好显示的准备。如果你的实现支持视图内容的可编辑性,UIViewController 类中的setEditing:animated:方法给了你在可编辑版本和不可编辑版本之间进行过度的一个地方。

动画block是另一个初始化与view相关改编的常用场所。动画支持是在UIView类里内建的,这使得使用动画改变视图的属性变得方便。你还可以使用 transitionWithView:duration:options:animations:completion:方法或transitionFromView:toView:duration:options:completion:去交换新旧两套view集。

更多关于动画师徒和初始化view过度的信息,请查看Animations。
过多关于如何使用view controller来管理与视图相关的行为,请查看View Controller Programming Guide for iOS.

与Core Animation层进行交互

每个视图对象有一个专门的核心动画层管理视图内容在屏幕上的外观和动画。尽管你可以通过view对象来做许多事,你同样可以直接使用相关的layer对象来做这些事。view的layer对象是储存在view的layer属性里的。

改变与视图相关联的layer类

与视图相关的layer的类型在视图被创建之后就不能被改变。因此,所有的视图使用UIView类的layerClass的类方法来指名layer对象的类。这个方法的默认实现会返回CALayer类,改变这个值得唯一途径是通过子类,覆盖这个方法来返回一个不一样的值。你可以使用一个不同种类的layer来改变这个返回值。eg.如果你的视图使用瓷片来显示一个大的可滚动区域,你可能会想要这个方法返回CATiledLayer类。

layerClass方法的实现是很简单的,实现应该只包括声明一个需要的类对象并返回它。eg.一个使用瓷片的view会有如下的实现:

+(Class)layerClass{
    return [CATiledLayer class];
}

每一个view在初始化过程中调用自己的LayerClass方法并使用这个返回值来创建它的layer对象。view通常会把自己分配为自己layer对象的代理。在这一点上,view拥有自己的layer并且view与layer的关系不能被改变。你不能分配一个view作为其他layer对象的代理。改变view的拥有关系或代理管理将会造成绘制问题并会导致潜在的应用程序的崩溃。

更多关于Core Animation提供的不同种类的layer对象,请查看Core Animation Reference Collection.

在view中嵌入layer对象

如果相对于view对象,你更喜欢直接在layer对象上进行操作,可以把自定义的layer对象加入到你的视图层次结构中。自定义的layer对象时CALayer类的一个实例,这个layer不被任何一个view拥有。通常用代码创建自定义的layer对象,并且使用Core Animation例程来合并他们。自定义的laye不接收、不参与响应链,但是会绘制自己并且根据Core Animation规则响应它的父视图或父layer的大小改变。

框3-2显示了一个viewDidLoad方法的例子,这个例子创建了一个自定义的layer对象并把它加入到了根视图里。这个layer是用来显示一个静态的图像动画的。在这个例子中,添加这个layer到view之下的layer里,而不是直接把这个layer添加到view自身。

框3-2

- (void)viewDidLoad{
    //Create the layer.
    CALayer *myLayer = [[CALayer alloc] init];

    // Set the contents of the layer to a fixed image. And set
    // the size of the layer to match the image size.
    UIImage *layerContents = [[UIImage imageNamed:"maImage"] retain];
    CGSize imageSize = layerContents.size;

    myLayer.Bounds = CGRectMake(0,0,imageSize.width,imageSize.height);
    myLAyer = layerContents.CGImage;

    //Add the layer to the view.
    CALayer *viewLayer = self.view.layer;
    [viewLayer addSublayer:myLayer];

    //center the layer in the view.
    CGRect viewBounds = backingView.bounds;
    myLayer.position = CGPointMake(CGRectGetMidX(viewBounds),CGRectGetMidY(viewBounds));

    [myLayer release];

}

你可以添加任意数量的子层并把他们整理到一个子层层次结构中。然而,在某种程度上,这些层必须附加到对象的视图层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值