在iOS开发开发过程中经常会用到界面元素的frame、bounds表示大小和位置的属性以及center、position、anchorPosition等单纯表示位置的属性。这些属性究竟什么含义?彼此间又什么关系呢?下面就来浅谈一番。

首先来说说frame和bounds。

frame:描述当前界面元素在其父界面元素中的位置和大小。
        bounds:描述当前界面元素在其自身坐标系统中的位置和大小。
        iOS以左上角为坐标原点(0,0),以原点向右侧为X轴正方向,原点下侧为Y轴正方向。iOS采用CGPoint来表示点在坐标系上X、Y位置。同时,iOS采用CGSize来表示界面元素的宽度和高度,即视图的大小。而CGRect则是结合了CGPoint和CGSize,用来表示矩形的位置和大小。它的origin表示矩形右上角所在位置(CGPoint),size表示矩形的大小(CGSize)。
        frame所描述的大小跟bounds所描述的大小是一致的,都是指界面元素的宽和高。但它们所描述的位置却不相同,frame描述的位置是指该界面元素左上角在父界面元素坐标系中的位置,而bounds描述的位置是指该界面元素左上角在自身坐标系中的位置,所以bounds描述的位置始终为(0,0)。可以说frame和bounds最大区别在于它们选取的坐标系不同。如下图:

下面再来说说center、position和anchorPosition三个单纯表示位置的属性。

说这三个属性前得先了解下CALayer。
        UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如frame,bounds等,实际上内部都是在访问它所包含的CALayer的相关属性。
       center:描述当前界面元素的中心点在其父界面元素中的位置。center只能通过界面元素本身访问,而CALayer没有提供外部访问的该属性,但通过前面的描述可以知道,访问界面元素的center属性肯定也是调用了CALayer的相关属性计算得出的。一般我们可以通过下面的计算得出center。

  1. center.x = frame.origin.x + frame.size.width * 0.5;
  2. center.y = frame.origin.y + frame.size.height * 0.5;

不过通常我们用不到这样的计算。
       接下来重点说说其它两个描述位置的属性position和anchorPosition。

  1. @property CGPoint position
  2. @property CGPoint anchorPoint

通过声明我们可以发现它们都是CGPoint类型。此刻我们把CALayer看作是一张打印纸被一根图钉钉在桌面上(相当于父界面元素的CALayer),可以想像这张打印纸可以绕着这根图钉旋转。那么图钉相对于打印纸的位置就可以用anchorPosition来描述,而这根图钉在桌面上的位置便是position。
      在iOS中,anchorPoint点的值是用一种相对bounds的比例值来确定的,在打印纸的左上角、右下角,anchorPoint分别为(0,0), (1, 1),也就是说anchorPoint是在单元坐标空间(同时也是左手坐标系)中定义的。类似地,可以得出在打印纸纸的中心点、左下角和右上角的anchorPoint为(0.5,0.5), (0,1), (1,0)。请参考下图,注意图中分iOS与MacOS,因为两者的坐标系不相同,iOS使用左手坐标系,坐标原点在左上角,MacOS使用右手坐标系,原点在左下角,我们看iOS部分即可。

再来看看position的原始定义: The layer’s position in its superlayer’s coordinate space。中文可以理解成为position是layer相对superLayer坐标空间的位置,很显然,这里的位置是根据anchorPoint来确定的。 至于如何确定,请看下面的公式。

  1. position.x = frame.origin.x + anchorPoint.x * bounds.size.width;
  2. position.y = frame.origin.y + anchorPoint.y * bounds.size.height;

如果单方面修改layer的position位置,会对anchorPoint有什么影响呢?修改anchorPoint又如何影响position呢?
       虽然说Position是根据anchorPosition来确定的,但根据代码测试,两者互不影响,受影响的只会是frame.origin,也就是layer坐标原点相对superLayer会有所改变。换句话说,frame.origin由position和anchorPoint共同决定,上面的公式可以变换成下面这样的。

  1. frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
  2. frame.origin.y = position.y - anchorPoint.y * bounds.size.height;

这就解释了为什么修改anchorPoint会移动layer,因为position不受影响,只能是frame.origin做相应的改变,因而会移动layer。
        Apple doc中还有一句描述是这样的:
  
        When you specify the frame of a layer, position is set relative to the anchor point. When you specify the position of the layer, bounds is set relative to the anchor point.
 
       当你设置图层的frame属性的时候,position点的位置(也就是position坐标)根据锚点(anchorPoint)的值来确定,而当你设置图层的position属性的时候,bounds的位置(也就是frame的orgin坐标)会根据锚点(anchorPoint)来确定。
       如果我们需要修改anchorPoint,但又不想要移动layer也就是不想修改frame.origin,那么根据前面的公式,就需要position做相应地修改。简单地推导,可以得到下面的公式。

  1. positionNew.x = positionOld.x + (anchorPointNew.x - anchorPointOld.x)  * bounds.size.width
  2. positionNew.y = positionOld.y + (anchorPointNew.y - anchorPointOld.y)  * bounds.size.height

其实没必要这么麻烦。修改anchorPoint而不想移动layer,在修改anchorPoint后再重新设置一遍frame就可以达到目的,这时position就会自动进行相应的改变。写成函数如下。

  1. - (void)setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{
  2. CGRect oldFrame = view.frame;
  3. view.layer.anchorPoint = anchorpoint;
  4. view.frame = oldFrame;
  5. }

以上内容是本人结合开发经验并参考了部分资料而撰写的,如有不妥之处还请不吝赐教,愿大家能够互相学习,共同进步。

转载自:http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/e20914053/article/details/49950307

frame、bounds表示大小和位置的属性以及center、position、anchorPosition的更多相关文章

  1. 视图UIView的大小和位置属性详解

    UIView类中定义了三个属性,分别是frame.bounds与center属性: IKit中的坐标系X轴正方向为水平向右,Y轴正方向为竖直向下. frame属性指的是视图在其父视图坐标系中的位置与尺 ...

  2. 初见IOS的UI之:UI控件的属性frame bounds center 和transform

    这些属性,内部都是结构体:CGRect CGPoint CGFloat 背景知识:所有的控件都是view的子类,屏幕就是一个大的view:每个view都有个viewController,它是view的 ...

  3. UIView 中 frame, bounds, center 属性的关系

    最近一直在学 iOS 开发,所以专门创建了这样一个类别,将自己学习中的一些问题整理,记录下来.由于自己是初学者,所以所写的文章非常基础,写这个类别一是为了给自己留下存 档,二是为了给和我有同样问题的初 ...

  4. Js位置与大小(1)——正确理解和运用与尺寸大小相关的DOM属性

    在web开发中,不可避免遇到要计算元素大小以及位置的问题,解决这类问题的方法是利用DOM提供的一些API结合兼容性处理来,所有内容大概分3篇左右的文章的来说明.本文作为第一篇,介绍DOM提供的与尺寸大 ...

  5. frame,bounds,center-三者的含义

    frame与bounds的区别比较 frame,bounds,center-三者的含义 偶然觉的,这三个属性有时候定位的时候,需要用.于是就来搞清楚,到底frame,bounds,center 这三个 ...

  6. frame.bounds和center

    CGPoint point=CGPoint(x,y);  //表示位置 CGSize size=CGSzieMake(width,height);  //表示大小 CGRect rect=CGRect ...

  7. iOS开发之 UIScrollView的frame、contentSize、contentOffset和contentInset属性

    ios中下拉图片变大效果 http://blog.csdn.net/mad2man/article/details/14169197 IOS中UIScrollView的frame.contentSiz ...

  8. WPF编程,窗口保持上次关闭时的大小与位置。

    原文:WPF编程,窗口保持上次关闭时的大小与位置. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details/8 ...

  9. windowsclient开发--使你的client执行时记住上次关闭的大小和位置

    差点儿全部的windowsclient都能够调整大小,所以用户依据自己的喜好调整client的大小和位置. 可是当该client退出后,又一次执行client的时候.我们往往又要调整自己喜好的大小和位 ...

随机推荐

  1. UVALive 6672 Bonus Cards 概率dp

    题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的 ...

  2. 亲身体验:Vultr超高性价比VPS评测教程

    最具性价比的vps是哪家?综合考虑vps稳定性.机房速度.vps硬件配置,美国linode一度是vps市场里的王牌:digitalocean vps迅速介入云主机市场,SSD固态硬盘性能秒杀竞争对手, ...

  3. Openjudge-计算概论(A)-求满足条件的3位数

    描述: 编写程序,按从小到大的顺序寻找同时符合条件1和2的所有3位数,条件为: 1.该数为完全平方数 2.该数至少有2位数字相同 例如,100同时满足上面两个条件. 输入输入一个数n,n的大小不超过实 ...

  4. ios 中Category类别(扩展类)小结

    类别 类别是一种为现有的类添加新方法的方式.利用Objective-C的动态运行时(runtime)分配机制,可以为现有的类添加新方法,这种为现有的类添加新方法的方式称为类别catagory,他可以为 ...

  5. mysql字符集问题

    背景:数据库表信息乱码问题 影响:数据库连接初始化中断 原因:init_connect参数设置问题,参数为不可执行语句. 1.1 DB字符集参数 #数据库中的字符集设置(以下全部为修改过后的结果) m ...

  6. java URL编程

    一.URL编程技术 URL是统一资源定位器的缩写,它是指向互联网“资源”的指针.URL表示了Internet上某个资源的地址.URL支持http,file,ftp等 多种协议.通过URL标识,可以直接 ...

  7. UVALive 2520 Holedox Moving(BFS+状态压缩)

    这个题目在比赛的时候我们是没有做出来的,但是听到他们说进制哈希的时候,感觉真的是挺高端的,于是赛后开始补题,本着我的习惯在看题解之前自己再试着写一遍,我当时存储状态的方法是string + map,我 ...

  8. android代码格式化方法小结

    转载:http://blog.csdn.net/androidzhaoxiaogang/article/details/7692526 Download the android-formatting. ...

  9. iosOC不可变数组遍历

    NSArray * array = @[@"1",@"2",@"3"]; NSLog(@"%@",array); //1 ...

  10. 《Windows驱动开发技术详解》之驱动程序调用驱动程序——通过设备指针调用其他驱动程序

    本节介绍“手动”构造各个IRP,然后将IRP传递到相应驱动程序的派遣函数里. 获得设备指针 每个内核中的句柄都会和一个内核对象的指针联系起来.ZwCreateFile内核函数可以通过设备名打开设备句柄 ...