一、坐标系
做iOS开发时,有很多东西都用不惯,比如没有单独设置View的位置和大小的方法,而要把位置和大小一起初始化,感觉有点麻烦。
在Cocos2d里就非常方便,因为Cocos2d的锚点可以很方便地设置子视图的位置,而iOS里没有锚点这个概念。
所以我把Cocos2d的锚点移植到了iOS里,并做了一些修改,使其成为了有着iOS特色的锚点。
Cocos2d里采用OpenGL ES坐标系,坐标原点在屏幕左下角。而iOS采用的是Quartz 2D坐标系,坐标原点在屏幕左上角。
在Cocos2d和iOS中分别把视图的坐标点设为(10,10),结果如下:
因为Cocos2d的视图是以视图的中心位置设置坐标点的,而iOS的视图是以左上角设置坐标点的。
二、锚点的概念
那么什么是锚点呢?下面以一个例子来说明:
比如要创建以下两个视图,橙色视图是蓝色视图的子视图,蓝色视图左上角在坐标(5,4)处,而橙色视图右边和蓝色视图对齐,有一半的高度处于蓝色视图外面:
按照iOS标准的创建视图的写法可以这样写代码:
1 | UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(5, 4, W, H)]; |
可以看到创建视图时就要计算视图左上角的坐标,非常麻烦。
而使用了锚点的代码可以这样写:
1 | UIView *blueView = [[UIView alloc] initWithSize:CGSizeMake(W, H)]; |
可见代码十分优雅,一开始先初始化视图大小,然后再设置视图的位置。
橙色视图的坐标点是(W, H),锚点是(1, 0.5),通过这两个点就可以设置视图的准确位置了,根本就不用去计算橙色视图的左上角的坐标(W - w, H - h/2)。
可以这样说:锚点是子视图用来设置位置的一个定位点,使用锚点就不会用子视图的宽高参与计算,省去了麻烦的计算,从而让代码更优雅。
三、锚点的取值范围
从下图可知,锚点的取值范围是[0, 1]:
设置一个子视图的坐标时,锚点(0, 0)表示把子视图的左上角放到该坐标的位置,锚点(0.5, 0.5)表示把子视图的中点放到该坐标的位置。
四、源码下载
通过Category
为UIView添加设置锚点的方法,让所有View的子类就可以使用该方法。
可以在https://github.com/poboke/OCElegant下载该代码。
将UIView+Frame
类添加到工程里即可,这个类里面还定义了一些获取和设置View的大小和位置的方法,比如设置锚点的方法:
1 | - (void)setPosition:(CGPoint)point atAnchorPoint:(CGPoint)anchorPoint |
代码里通过self.width
就能取到View的宽度了,而不用写self.frame.size.width
。
通过代码也可以清楚地知道:实现锚点的方法其实很简单,就是在setPosition:atAnchorPoint:
方法里面利用锚点和子视图的宽高进行计算,从而调整了子视图的位置。