下面有几个比较重要的关于view的大小以及位置的属性
UIScreen.mainScreen.bounds
全屏大小
UIScreen.mainScreen.applicationFrame
不包括状态栏的大小(由于状态栏高度为20,所以height也就比bounds小20了),当状态栏隐藏时,也就跟bounds一样了。
UIView的大小与位置,
大小有本UIVIew.bounds.size来控制
位置由本UIVIew.center来控制
本UIView.center的数值是本UIView相对于父UIView的坐标系远点的距离
本UIView.center在本UIView中的位置由layer.anchorPoint来控制(不要想当然的认为center就是正中心)
从结果上来看UIView.frame.x,UIView.frame.y是UIView左上角相对于父UIView的坐标原点的距离,UIView.frame.width =UIVIew.bounds.width,UIView.frame.height=UIVIew.bounds.height
所以可以理解为UIView.frame只是设定UIView大小和位置后的属性体现,然而由于他们之间的可逆计算关系,也可以通过设定frame来改变,UIView的大小和位置,也算是屁股决定脑袋吧。
下面是他们的对应关系
UIView.frame.x = UIView.center.x - UIView.bounds.width * UIView.layer.anchorPoint.x
UIView.frame.y = UIView.center.y - UIView.bounds.width * UIView.layer.anchorPoint.y
可以看出center在UIView的点位置实际上是由anchorPoint决定的,如果anchorPoint是[0,0],那么center的位置就是在UIView的左上角,如果anchorPoint是[1,1],那么center就是在UIView的右下角
UIView.center.x = UIView.frame.x + UIView.frame.width * UIView.layer.anchorPoint.x
UIView.center.y = UIView.frame.y + UIView.frame.width * UIView.layer.anchorPoint.y
因为UIView.frame.width==UIView.bounds.width,UIView.frame.width==UIView.bounds.width,所以上面的关系很明确
1.想让子UIView统一变更一下屏幕位置,可以调整一下本UIVIew的bounds.origin大小,这个值代表本UIView在自己坐标系的位置(说起来有点儿绕),改变bounds.origin后,本UIView本身是没什么位置变化的,那么相对的等于其坐标系向着相反方向移动了,因为子视图是跟着父视图的坐标系走的,那么就相当于子视图也都跟着向着相反方向移动。
例如视图viewA的子视图ViewB,默认viewA.bounds.origin =(0, 0),如果设置为viewA.bounds.origin =(5, 5),说明viewA相对于其坐标系向右下方分别移动了5个点,viewA在屏幕上的位置没变,那么相当于viewA的坐标系向左上方分别移动了5个点,也就是视图viewB在屏幕上的位置向左上方分别移动了5个点。
大家都用过UIScrollView,其实它本身就是简单的UIView,通过添加一些方法,来控制其bounds.origin属性,然后整体移动其子视图大小,从而起到滚动子视图的效果。
详细可以参照这片文章
改变UIView.center在本UIView坐标系的位置,可以调整layer.anchorPoint,当对本UIVIew按比例扩大缩小,或者旋转时,都是以这个layer.anchorPoint为基准的。注意单独设定layer.anchorPoint后,UIView.frame.x和y也会跟着变,而UIView.center的数值不会变。(从这点儿也可以看出决定UIView位置的是center和anchorPoint,而frame只是一个结果属性)
关于视图坐标的转换
视图的坐标都是相对于其父视图坐标系的
那么视图在其它视图的坐标系中的位置,就需要进行位置转换。
有两个函数专门进行这种转换
func convertRect(_
rect
: CGRect,toView view
: UIView?) -> CGRectfunc convertRect(_
rect
: CGRect,fromView view
: UIView?) -> CGRect
这两个方法是等价的,主要看是对象哪个视图来调用了。
比如
viewA.convertRect(rect, toView:viewB)
意思就是在视图viewA里的一个矩形框(包括坐标和宽高)在viewB坐标系的位置
等价的另外一种写法
viewB.convertRect(rect, fromView:viewA)
根据文档要求ViewA和ViewB都必须在同一个UIWindow系统里。
所以猜想,其实都是先转换到UIWindow坐标系,然后再转换到对象View的坐标的。
如果是这样的写法
viewA.convertRect(ViewC.frame, toView:viewB)
这通常指的是viewC是viewA的直接子视图,得出ViewC如果是在ViewB坐标系的位置,viewC和viewB只要在同一个UIWindow就可以了,他俩之间可以有也可以没有所属关系。