ios编程基础—视图
视图 Views
视图(view )是UIView 或其子类的实例(对象object)。应用程序借助视图提供可视界面。视图同时也是一个反应器(UIView 是UIResponder的子类),因此视图可以提供交互,如轻拍或扫划。视图序列(view hierarchy)是视图的基本组织方式。视图可以有子视图(subview)和父视图(superview)(只能有一个直接父视图)。视图从界面(父视图)中移走(隐藏、移动)后,其子视图也随之移走(隐藏、移动)。视图可以来自nib文件(storyboard),也可以用代码实现。
窗口Window
视图序列的顶端是应用程序窗口(window),它是UIWindow(或其子类)的一个实例。应用程序只能有一个主窗口(在没有外接显示器的情况下),它在程序启动时生成,一直存在,直到程序结束。它是其它所有可见视图的背景和顶级父视图。应用程序窗口必须填满设备屏幕,在窗口实例化时将窗口的frame设为屏幕的bounds来实现(如果采用main storyboard编程,会自动实现)。
窗口是与应用程序(app)同时存在的。当app启动时,UIApplicationMain函数实例化一个app委托类(delegate),并保留这个实例(直到app结束)。然后生成一个窗口实例,并赋值给这个app委托实例的window属性,因此可以保证窗口在app的生命周期内一直存在。
一般不会在主窗口内添加视图内容,而是先获得一个视图控制器(view controller)实例,并将之赋值给主窗口的rootViewController属性。此时视图控制器的主视图会成为主窗口的根视图(root view),主窗口中所有其它视图都将是根视图的子视图。因此根视图是整个视图序列中最顶级的对象。App界面只有在包含它的窗口成为app的关键窗口后才能变为看见的。这可以调用UIWindow的实例方法来实现。一般情况下这都是自动完成的。
Subview and Superview
UIView有superview属性和subview属性(UIView对象数组)用来判断某视图在视图序列中的位置,方法isDescendantOfView用于判断是不是某视图的子视图,数字tag属性 viewWithTag可以判断某视图的所有高阶视图是否有满足某tag的视图。addSubview方法使一个视图成为另一个的子视图,removeFromSuperview方法将子视图从它的父视图中移除。移除子视图将会使其消失,如果后面还要用它,必须先将其赋值给某属性来保留它。
视图可以部分或全部出现在父视图的外面,一个视图可以部分或全部与另一个视图重叠。视图显示顺序取决于视图序列。同一个父视图的同级(兄弟辈)子视图逐个按顺序显示,后面出现的会覆盖先出现的,子视图会覆盖父视图。
父视图的透明度会被子视图继承。父视图可以选择性限制子视图的显示,通过clipsToBounds属性使其不显示父视图外面的那部分。父视图负责管理子视图(内存),父视图的大小发生改变时,子视图随之改变。
Visibility and Opacity
可以把hidden属性设置为true使得隐藏视图,隐藏只是让视图不可见,并未移除视图,视图被隐藏后一般不能接收触摸事件。通过backgroundColor属性(UIColor值)可以设置视图背景,当该属性值为nil时,视图变为透明的。可以通过alpha值调节视图的透明度(包括其内容与背景,并会影响其子视图),1.0为不透明,0.0为透明。如果父视图的alpha为0.5,其所有子视图的透明度不会高于0.5。完全透明的视图相当于被隐藏,连同其子视图均不可见。opaque属性只是对绘制系统的一种提示,对视图的样子影响不大,默认为true,不必改变。
Frame
视图frame属性(CGRect值),表示视图在其父视图坐标系中的位置(左上角)和大小(x,y,width,height)。视图的坐标原点默认是左上角,x向右为正,y向下为正。改变frame值会改变其位置、大小或二者均改变。UIView 指定构造器为init(frame:),切记在实例化视图时要设定frame 值,默认frame值为CGRectZero。
Bounds and Center
视图bounds属性(CGRect值),表示视图在自身坐标系中的位置和大小(0,0,width,height),视图center属性(x,y)反映视图在父视图坐标系的位置。当bounds发生改变时,center不变,也就是说其在父视图坐标系中的位置保持不变。当center改变时,bound也不变,二者是视图的两个独立指标。视图的大小bounds.size(宽度和高度)改变时,其center保持不变,由于其顶点位置已改变,其frame也会改变。当bounds的原点(origin)改变时,由于其center不变,frame也不变。其自身坐标系会发生反向变化。视图bounds的改变,不影响子视图的大小,但可能改变其位置。同一个窗口内不同视图的坐标系可以相互转换。convertPoint:fromView:, convertPoint:toView:,convertRect:fromView:, convertRect:toView,如果第二个参数为nil,对应的是窗口。
Window Coordinates and Screen Coordinates
设备屏幕没有frame,但有bounds,主窗口没有父视图,其frame的设置是基于屏幕的bounds的。所以窗口坐标系一般就是屏幕坐标系。
let w = UIWindow(frame: UIScreen.mainScreen().bounds)
在iOS 9后,可以let w = UIWindow()
早期屏幕坐标系是固定不变的,iOS 8之后,屏幕坐标系会随着设备旋转而改变。正常情况下高度大于宽度,设备横着时宽度大于高度。你可以通过UIScreen’s fixedCoordinateSpace属性获得固定不变的坐标系,通过UIScreen’s coordinateSpace属性得到可变坐标系。