简单的说,frame决定视图左上角点在其superview内的位置,bounds决定该视图左上角点在本地坐标系统中的位置。

演示代码如下:

UIView *mainView = self.window.rootViewController.view;
UIView *v1 = [[UIView alloc] initWithFrame:
CGRectMake(100,100,100,100)];
v1.backgroundColor = [UIColor redColor];

UIView *v2 = [[UIView alloc] initWithFrame:
CGRectInset(v1.bounds,20,20)];
v2.backgroundColor = [[UIColor greenColor]];

UIView *v3= [[UIView alloc] initWithFrame:
CGRectInset(v2.bounds,5,5)];
v3.backgroundColor = [[UIColor blackColor]];

[mainView addSubview:v1];
[v1 addSubview:v2];
[v2 addSubview:v3];

创建了一个背景为白色的主视图,在主视图上,添加三个子视图v1,v2,v3。其中v1背景颜色为红色、v2背景颜色为绿色,并且是v1的子视图、v3背景颜色为黑色,并且是v2的子视图;此时在mainView中显示的如下图所示,v2内嵌到v1中,并且边界距离v1的边界为(20,20),v3内嵌到v2中,且距离v2的边界为(5,5);

ios UIView 设置 背景图 uiview bounds_背景颜色



继续如下代码

CGRect r = v1.bounds;
r.origin.x += 10;
r.origin.y += 10;
v1.bounds = r;

此处容易被代码的形式欺骗,中间两行代码的意思可能被理解为视图v1的本地坐标系统原点向右下角移动{10,10}(PS:iOS坐标系统,以视图的左上角为零点,x轴向右为正,y轴向下为正),那么产生的结果应该是子视图也向右下角移动。

其实这两行代码是将视图v1的左上角点,设置为{10,10},(默认为{0,0}),此时v1的本地坐标系统的原点相当于向左上角移动了{10,10},即整个坐标系统向左上角移动。所以导致的结果是该视图的子视图,也向左上角移动{10,10}。得到的下图也证实了这一点:

ios UIView 设置 背景图 uiview bounds_子视图_02



《Programming IOS 7 , 4 edition》中关于上段代码的解释如下

ios UIView 设置 背景图 uiview bounds_背景颜色_03


黄色高亮语句,将View左上角{0,0}点,称为{10,10}点,即将bounds的原点设置为{10,10}。此时我们本地坐标系原点{0,0}点向左上角移动。所有view的bounds,默认原点都为{0,0}点,即其左上角。所以代码中对origin的操作,其实是设置左上角点在虚拟坐标系中的位置,也就相当于改变本地坐标系零点的位置。


将上段代码修改为

CGRect r = v2.bounds;
r.origin.x += 5;
r.origin.y += 5;
v2.bounds = r;


此时看到的结果是,v2在v1中的位置并没有发生变化,而v3在v2中的位置,也是向左上角移动,即bounds的修改,只是会影响到子视图的位置变化,对视图本身不会起到作用。

ios UIView 设置 背景图 uiview bounds_坐标系统_04


继续修改上段代码

CGRect r = v2.frame;
r.origin.x += 20;
r.origin.y += 20;
v2.frame = r;



此时看到的结果是,视图v2在v1中的位置向右下角移动{20,20},并且v2的子视图v3也随着v2一起向右下角移动。说明frame的修改,影响到的是view本身在superview中的位置,不会影响其子视图在该view内的位置。

ios UIView 设置 背景图 uiview bounds_坐标系统_05


总结起来对frame与bounds的理解:

对于拥有superview的视图来说,此时该视图的左上角点在superview中的位置,由该视图的frame.origin决定,即frame是以其superview的坐标系统来描述此视图的。

同时,对于每个view的本地坐标系统bounds,默认的零点为该视图的左上角点。此时左上角点的坐标为{0,0},当改变bounds.origin的值时,其实是设置该视图左上角点在此坐标系统内的位置。即bounds.origin的值,是视图左上角在本地坐标系统的位置。