探究IOS中UI控件的位置(一):Frame、Bounds和Center

1.三个属性的基本介绍:

    (1)frame:描述当前视图在其父视图中的位置和大小。

    (2)bounds:描述当前视图在其自身坐标系统中的位置和大小。

    (3)center:描述当前视图的中心点在其父视图中的位置。

2.必须明确的几个逻辑原点:

      1.位置是相对的,想要表示一个物体的位置必须有参照系。(不同的参照系对相同位置的表示有什么不同?)

      2.控件的原始坐标系:默认控件的左上角为原点,值{0,0},原点出发水平向右是x轴正方向,递增;原点出发垂直向下是y轴正方向,递增。

      3.控件的bounds.origin(最初值都是{0,0})和frame.origin代表的都是控件左上角点的坐标。可以修改。(如何修改,会有什么影响?)

      4.bounds.size和frame.size都表示控件的大小,永远一样。(size的改变是如何影响bounds和frame的?)

      5.bounds代表本地(控件自己的)坐标系,frame代表父控件坐标系。坐标必须在同一个坐标系中才能比较。

3.探索bounds和frame的区别和联系

      一般大家对frame的改变和影响比较熟悉,但是对bounds改变比较陌生。所以,下面就对父控件、子控件的bounds.origin和bounds.size分为四种情况进行组合变换来探究。通过setBounds方法来改变bounds值。

- (void)viewDidLoad {

[super viewDidLoad];

//添加父控件orangeView

UIView * orangeView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];

orangeView.backgroundColor = [UIColor orangeColor];

[self.view addSubview:orangeView];

//添加子控件yellowView

UIView * yellowView = [[UIView alloc]initWithFrame:CGRectMake(20, 20, 100, 100)];

yellowView.backgroundColor = [UIColor yellowColor];

[orangeView addSubview:yellowView];

}

输出bounds和frame值:

orangeView: bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

图 3.0  添加两个控件

3.1 保持bounds.size不变,只改变bounds.origin

 3.1.1 父控件:

[orangeView setBounds:CGRectMake(-30, -30, 200, 200)];

    输出值:

orangeView: bounds:{{-30, -30}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

      从输出结果可以得出:父控件的bounds值变为修改后的值,frame不变;子控件bounds值不变(意料之中),值得注意的是,虽然子控件的位置移动了(相对于屏幕,示例程序是向右下方移动;相对于父控件的话,其实子控件位置不变,因为frame不变),但是子控件的frame不变。(父控件通过改变自身的bounds.origin值(自身坐标体系)抵消了子控件位移造成的frame.origin的改变(子控件的frame和父控件的bounds在同一个坐标体系中,因此可以互相抵消))

图 3.1  只改变父控件的bounds.origin

  3.1.2 子控件:

[yellowView setBounds:CGRectMake(-30, -30, 100, 100)];

    输出值:

orangeView: bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{-30, -30}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

      从输出结果可以得出:父控件的frame和bounds值都不变,子控件只有bounds变为修改后的值,frame值不变,子控件位置也不变。

      小结:从3.1.1和3.1.2的情况可以分析出:只要bounds值的origin被修改,size值不变,此时无论父控件还是子控件,只有被修改的bounds值会变为修改值,其他的值不变。但要注意:修改父控件的bounds值的origin值会导致子控件的位置改变(相对于屏幕)。

3.2 保持bounds.origin不变,只改变bounds.size

3.2.1 父控件

[orangeView setBounds:CGRectMake(0, 0, 250, 250)];

    输出值:

orangeView: bounds:{{0, 0}, {250, 250}}--frame:{{75, 75}, {250, 250}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

      从输出结果可以得出:父控件的bounds值变为修改值,frame值发生改变;子控件的bounds和frame不变。父控件的图形变换规律是:以变换前的center为中心,左右、上下等距离扩大或缩小。因此,假设原子父控件的frame = {{x, y}, {w, h}},修改后的父控件bounds = {{0, 0}, {w1, h1}},那么变换后的frame = {{x-(w1-w)/2, y-(h1-h)/2}, {w1, h1}};子控件的位置(相对于父控件)不变,因为frame没变。(图中的绿色控件是父控件原来的位置,作为对照)

图 3.2  只改变父控件的bounds.size

3.2.2 子控件

[yellowView setBounds:CGRectMake(0, 0, 250, 250)];

    输出值:

bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {250, 250}}--frame:{{-55, -55}, {250, 250}}

      从输出结果可以得出:子控件的bounds值变为修改值,frame值发生改变;父控件的bounds和frame不变。子控件的图形变换规律和3.2.1中子控件一样;子控件位置(相对于父控件)改变,因为frame变了。

      小结:从3.2.1和3.2.2的情况可以分析出::只要bounds值的size被修改,origin值不变,此时无论父控件还是子控件,被修改控件的bounds值变为修改值,frame值也会改变(计算公式如上),其他的值不变。  

3.3 同时改变bounds.origin和bounds.size

      由3.2和3.3分析可以推测出结果(已验证):

      1.父控件bounds和frame改变,子控件位置改变(相对于屏幕)。

图3.3  改变父控件的bounds.size和bounds.origin

      2.和3.2.2的到的结果相同。

      小结:bounds.size的改变要优先于bounds.origin改变进行处理。

综述:

    1.bounds.size改变时,当前控件的frame值改变,bounds值变为改变后的值,但不影响其他控件两个参数值。

    2.bounds.origin改变时,当前控件的frame值不变,bounds值变为改变后的值,但不影响其他控件两个参数值。

    3.bounds.size的改变要优先于bounds.origin改变进行处理。

    4.控件的bounds.size或bounds.origin的改变,只要改变了坐标系,在同一个坐标系中的其他的控件的位置(相对于屏幕)也会受到影响。

   5.以上规律对于控件是子控件或是父控件无需考虑。

4 应用场景

     苹果官方控件UITableView和UICollectionView就有很好的利用综述中第4点的特性来改变cell的移动的。UITableView或UICollectionView相当于父控件,cell相当于子控件,当滑动屏幕的时候,不断地改变tableview或collectionview的bounds.origin,从而使所有的cell相对于屏幕的位置发生变化,产生向上或向下滚动的效果,而cell的frame并没有发生改变,这样就不用在滑动过程中重新计算cell的frame值。

参考文章:

    1.深入探究frame和bounds的区别以及setbounds使用 - CocoaChina_让移动开发更简单

    2.详解UIView的frame、bounds和center属性 - 移动开发 - ITeye技术网站

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容