首页 > 代码库 > 【iOS7的一些总结】8、破解UIView中坐标系的秘密:关于UIView中的frame、bound和center
【iOS7的一些总结】8、破解UIView中坐标系的秘密:关于UIView中的frame、bound和center
对于刚刚接触iOS开发不久的新手来说,UIView中的frame、bound和center的确容易产生思维的误区,尤其是想要对视图类的bound这个概念若想要理解深入,真的要花一番功夫。在经过一系列查阅参考资料和动手试验之后,终于对这几个概念产生了一些领悟,记录于此可供有同样困惑的同学参考。
首先贴一篇博文做参考,http://blog.csdn.net/mad1989/article/details/8711697;这篇博文已经对UIView的frame和bound做了一些阐述,但是我依然觉得有些地方有些语焉不详,因此在这里通过自己的一些实验对其做一些补充,以期让读者不再有任何的疑惑。
在xcode中新建一个空工程,在AppDelegate.m文件的didFinishLaunchingWithOptions:(NSDictionary *)launchOptions函数中加入下面的程序:
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 100, 200, 200)]; [view1 setBounds:CGRectMake(25, 25, 200, 200)]; [self.window addSubview:view1]; UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; view2.backgroundColor = [UIColor redColor]; [view1 addSubview:view2]; NSLog(@"view1 frame:%@========view1 bounds:%@========view1 center:%@",NSStringFromCGRect(view1.frame),NSStringFromCGRect(view1.bounds),NSStringFromCGPoint(view1.center)); NSLog(@"view2 frame:%@========view2 bounds:%@========view2 center:%@",NSStringFromCGRect(view2.frame),NSStringFromCGRect(view2.bounds),NSStringFromCGPoint(view2.center)); [view1 release]; [view2 release];
程序执行之后将会在主屏幕上显示我们新添加的两个视图对象,如下图所示。
除此之外,在控制台输出窗口上,还会显示以下内容:
view1 frame:{{50, 100}, {200, 200}}========view1 bounds:{{0, 0}, {200, 200}}========view1 center:{150, 200}
view2 frame:{{0, 0}, {100, 100}}========view2 bounds:{{0, 0}, {100, 100}}========view2 center:{50, 50}
在上述程序中,我们在主窗口上添加了两个矩形视图对象,父视图为绿色,起始点为(50,100),长宽为(200,200)。在添加红色的子视图view2的时候,由于我们采用的初始化方法是initWithFrame(不存在initWithBound方法),view2就设置了其在父视图坐标系中的相对位置和大小,即相对于父视图坐标,起始点为原点(即左上角),尺寸为(100,100)。若改变其初始frame,则其相对于父视图的位置也会改变。如将程序中view2产生的代码改为:
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 80, 80)];
则程序运行结果如下:
同时,view2的控制台输出信息也相应变为:
view2 frame:{{20, 20}, {80, 80}}========view2 bounds:{{0, 0}, {80, 80}}========view2 center:{60, 60}。
我们也发现,在默认情况下,视图的bound起始点一直是(0,0);
而现在我想到的一点是,如果我们改变了视图对象的bound成员,那该对象将会产生怎样的变化呢?
添加代码:
[view2 setBounds:CGRectMake(50, 50, 100, 100)];同时撤销掉刚刚对其frame的改动,依旧为(0,0,100,100)。程序运行的结果如下图:
跟第一张图相比,完全没有任何变化。也就是说,改变了bound的起始点,并不会造成视图本身相对于父视图的位置移动。因为,像刚才这样将bound起始点设为(50,50),是将子视图自身坐标改变。而视图在创建的时候,initWithFrame函数参照父坐标的位置构建子视图,所以子视图本身的坐标的改动,并不会影响自身。那bound起始点的不同,究竟影响的是谁呢?
为了探寻这个问题,我们在view1创建之后,新加入下面这条语句:
[view1 setBounds:CGRectMake(25, 25, 200, 200)];
此时view1的自身坐标被改变。程序运行的结果如下图所示:
从图中可以看出来,绿色父视图的位置依然没有改变,但是红色的子视图的位置向左上方经纬度各移动了25像素的距离。为什么会出现这种现象呢?父视图bound的起始点设为了(25,25),也就意味着绿色方块的左上角的像素点的本地坐标不再是(0,0),而是(25,25)。而子视图的起始渲染位置在父视图的(0,0)点,相应的也就移动到父视图的左上角了。
为了验证这个结论,我们再次修改以下程序,将view2的绘制语句改为:
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(25, 25, 100, 100)];
然后运行一下程序,显示结果如下:
可见,经过绘制子视图的时候相对于父视图的补偿,子视图和父视图的右上角又重合了,这也从另一个角度证明了我们的结果。