zoukankan      html  css  js  c++  java
  • frame、bounds表示大小和位置的属性以及center、position、anchorPosition

           在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。

    [html] view plain copy
     
    1. center.x = frame.origin.x + frame.size.width * 0.5;  
    2. center.y = frame.origin.y + frame.size.height * 0.5;  


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

    [objc] view plain copy
     
    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来确定的。 至于如何确定,请看下面的公式。
       
      

    [objc] view plain copy
     
    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共同决定,上面的公式可以变换成下面这样的。
       
       

    [objc] view plain copy
     
    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做相应地修改。简单地推导,可以得到下面的公式。
       
       

    [objc] view plain copy
     
    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就会自动进行相应的改变。写成函数如下。

    [objc] view plain copy
     
    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

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/Jenaral/p/5443857.html
Copyright © 2011-2022 走看看