UIKit
坐标系每一个 View
都定义了他自己的坐标系,如下图所示,x
轴指向右方,y
轴指向下方:
注意:
这个逻辑坐标系并不关注包含在其中 View
的宽度和高度,整个坐标系没有边界向四周无限延伸。
我们在坐标系中放置四个子 View
,每一次色块代表一个 View
:
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
redView.backgroundColor = [UIColor colorWithRed:0.815 green:0.007
blue:0.105 alpha:1];
UIView *greenView = [[UIView alloc] initWithFrame:CGRectMake(150, 160, 150, 200)];
greenView.backgroundColor = [UIColor colorWithRed:0.494 green:0.827
blue:0.129 alpha:1];
UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(40, 400, 200, 150)];
blueView.backgroundColor = [UIColor colorWithRed:0.29 green:0.564
blue:0.886 alpha:1];
UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(100, 600, 180, 150)];
yellowView.backgroundColor = [UIColor colorWithRed:0.972 green:0.905
blue:0.109 alpha:1];
[mainView addSubview:redView];
[mainView addSubview:greenView];
[mainView addSubview:blueView];
[mainView addSubview:yellowView];
bounds
Apple
关于 UIView
的文档中是这样描述 bounds
属性的:
bounds矩形…描述了该视图在其自身坐标系中的位置和大小。
一个 View
可以被看作是定义在其所在坐标系平面上的一个矩形的可视区域,View
的边界表明了这个矩形可视区域的位置和大小。
假设我们的 View
宽320像素,高480像素,原点在(0,0)。那么这个 View
就变成了整个坐标系平面的观察口,它展示的只是整个平面的一小部分。位于该 View
边界外的区域依然存在,只是被隐藏起来了。
一个 View
提供了其所在平面的一个观察口,View
的 bounds
矩形描述了这个可是区域的位置和大小。
接下来我们来试着修改 bounds
的原点坐标:
CGRect bounds = mainView.bounds;
bounds.origin = CGPointMake(0, 100);
mainView.bounds = bounds;
当我们把 bound
原点设为(0,100)后,整个画面看起来就像这样:
修改 bounds
的原点就相当与在平面上移动这个可视区域。
看起来好像是这个 View
向下移动了100像素,在这个 View
自己的坐标系中这确实没错。不过这个 View
真正位于屏幕上的位置(更准确的说在其父 View
上的位置)其实没有改变,因为这是由 View
的 frame
属性决定的,它并没有改变:
frame矩形…定义了这个View在其父View坐标系中的位置和大小。
由于 View
的位置是相对固定的,你可以把整个坐标平面想象成我们可以上下拖动的透明幕布,把这个 View
想象成我们观察坐标平面的窗口。调整 View
的 Bounds
属性就相当于拖动这个幕布,那么下方的内容就能在我们 View
中被观察到:
修改 bounds
的原点坐标也相当于把整个坐标系向上拖动,因为 View
的 frame
没由变过,所以它相对于父 View
的位置没有变化过。
其实这就是 UIScrollView
滑动时所发生的事情。注意从一个用户的角度来看,他以为时这个 View
中的子 View
在移动,其实他们的在坐标系中位置(他们的 frame
)没有发生过变化。
一个 scroll view
并不需要其中子 View
的坐标来使他们滚动,唯一要做的就是改变他的 bounds
属性。知道了这一点,实现一个简单的 scroll view
就没什么困难了。我们用一个 gesture recognizer
来识别用户的拖动操作,根据用户拖动的偏移量来改变 bounds
的原点:
和真正的 UIScrollView
一样,我们的类也有一个 contentSize
属性,你必须从外部来设置这个值来指定可以滚动的区域,当我们改变 bounds
的大小时我们要确保设置的值是有效的。