视图是用户在屏幕上所看到的,也是用户通过触摸屏幕进行交互的东西,因此视图是一个应用可视化 可触摸表现的主要组成部分。
1.1 子视图和父视图
UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(50, 150, 200, 200)]; v1.backgroundColor = [UIColor redColor]; UIView *v2 = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 80, 80)]; v2.backgroundColor = [UIColor greenColor]; UIView *V3 = [[UIView alloc] initWithFrame:CGRectMake(70, 70, 80, 80)]; V3.backgroundColor = [UIColor blackColor]; [self.view addSubview:v1]; [v1 addSubview:v2]; [v1 addSubview:V3];
上面的代码创建了视图 v1 v2 v3,v2 v3是v1的子视图 。
运行结果:
视图在视图的层次结构的位置并不影响它是如何绘制的,但是会影响绘制的顺序,上面的例子可以体现出来
不同层级时:父视图先绘制
相同层级时:“更早”加入的视图先绘制
视图层次结构的其他效果:
如果视图从它的父视图移除或移入,它的子视图将会和它一起
如果视图的尺寸改变,它的子视图能够自动重新调整尺寸
视图的透明度将会被子视图继承
视图可以选择性的限制它的子视图的绘制,这样任何视图之外的部分都不会显示,这称为剪切,并且是通过设置视图的clipsToBounds属性进行控制的。
父视图拥有他们的子视图,从内存管理的角度来看,和NSArray拥有他们的元素很像,它保留它们并负责当该子视图不再是它的子视图的时候(从这个视图的子视图集合移除)或者不再存在时释放它们。
UIView有一个superview属性(一个UIView)和subviews属性(一个由UIView组成的NSArray)。
1.2 应用程序窗口
视图的顶层是窗口UIWindow(UIView的子类),一个应用至少有一个UIWindow的实例,该实例占据整个屏幕,是其他所有可见视图的最终父视图。
应用创建窗口有三种方法:
第一种是不使用xib和串联图,用代码创建,代码如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [self.window makeKeyAndVisible]; return YES; }
application:didFinishLaunchingWithOptions:是应用程序委托的一个方法,应用完成启动的时候会调用这个方法,UIWindow实例必须在应用的整个生命周期中存在,所以委托中有个一window保留它,makeKeyAndVisible消息用以显示应用界面.
第二种是使用串联图:
这种办法不需要写任何代码,我现在xcode的版本是6.0,创建项目选择single view会自动创建一个串联图(.storyboard文件),在Info.plist文件中的“Main storyboard file base name”指定即可,默认已经指定了,当然也可以自己创建一个storyboard文件重新指定。
在这种情况下,UIApplicationMain实例化应用程序委托后,它会请求委托的window属性,如果为nil,UIApplicationMain将会创建一个UIWindow实例并赋值给委托的window属性,串联图的initial view controller(初始视图控制器)实例化并赋值给window的rootViewController属性,随后向window发送makeKeyAndVisible消息以显示出来,这些都是UIApplicationMain在后台完成的,所以application:didFinishLaunchingWithOptions:方法的实现是空的。
第三种是使用xib文件:
1.删除Info.plist文件中的“Main storyboard file base name”一项。
2.创建一个xib文件,拖一个Window到画布中(包含一个Window就行)。
3.将xib文件 File's Owner的Identity inspector中的class设置为应用程序代理类。
4.在代理类中添加如下属性:
@property (strong, nonatomic) IBOutlet UIWindow *window;
(代理类的头文件原本有window属性,改成上面一样即可)
5.将window属性连接起来。
6.在application:didFinishLaunchingWithOptions:方法中加载xib文件,代码如下:
[[NSBundle mainBundle] loadNibNamed:@"View" owner:self options:nil];
1.3 视图的几个重要属性
1 frame 声明如下:
@property(nonatomic) CGRect frame;
frame 表示的是视图矩阵在父视图中的位置,用的是父视图的坐标系统,默认情况下,父视图的坐标系统会以左上角为原点,x坐标向右,y坐标向下,视图创建的时候应该设置frame ,就像上面那样,不设置的话 它的默认值是{{0,0},{0,0}}。
2 bounds 声明如下:
@property(nonatomic) CGRect bounds;
bounds 和 frame 只有唯一一个不同点,
frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)
bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)
3 center 声明如下:
@property(nonatomic) CGPoint center;
center 无论从字面意思还是类型来看都知道表示的是一个中心点,和bounds一样参照点是本身坐标系统。
4 transform 声明如下:
@property(nonatomic) CGAffineTransform transform;
transform 用来提供旋转 缩放 平移子类的变换,默认情况下transform的值为CGAffineTransformIdentity(没有可见效果),视图的任何变换都是围绕center来进行的,center保持不变。
改变transform 的值使用以“CGAffineTransformMake” 开头的函数。
演示:
UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(50, 150, 200, 200)]; v1.backgroundColor = [UIColor redColor]; [self.view addSubview:v1]; v1.transform = CGAffineTransformMakeRotation(45 * M_PI/180);
其他变换效果都大同小异,就不一一演示了。