iOS开发之如何保证控件位置不变,增加触控范围(即frame和bounds的区别)

       大佬儿们,我又双叒叕的来了,大家有没有被问到过frame和bounds有什么区别这样的面试题?或者是如何保证Button位置不变,增加点击范围这样的面试题?

       什么?没有遇到过!!!哇,如果you know,大佬,大佬,我向你膜拜膜拜,如果you don`t know,那你真的是太幸运了,快来跟我一起揭开frame和bounds若隐若现的面纱吧!

       首先,认识一下frame和bounds,两者都是CGRect类型的结构体,包含一个CGPoint(起点)和一个CGSize(尺寸)子结构体,系统的定义如下:

struct CGRect {
    CGPoint origin;
    CGSize size;
};

       origin决定了View的起点,size决定了View的尺寸。 

       具体使用如下:

    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 100);
    btn.bounds = CGRectMake(0, 0, 200, 200);
    [btn setBackgroundColor:[UIColor blueColor]];
    //[btn setImage:[UIImage imageNamed:@"giftBtn_black"] forState:UIControlStateNormal];
    //btn.layer.borderWidth = 2.0f;
    [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    [btn setTitle:@"中心点" forState:UIControlStateNormal];
    [self.view addSubview:btn];
    
    NSLog(@"\n原始frame:(100, 100, 100, 100),原始bounds:(0, 0, 200, 200),原始center:(150,150)\n输出frame:%@,输出bounds:%@,输出center:%@",NSStringFromCGRect(btn.frame),NSStringFromCGRect(btn.bounds),NSStringFromCGPoint(btn.center));
    
    UIView *centerView = [[UIView alloc] initWithFrame:CGRectMake(148, 148, 4, 4)];
    centerView.backgroundColor = [UIColor redColor];
    centerView.layer.cornerRadius = 2.0;
    centerView.clipsToBounds = YES;
    [self.view addSubview:centerView];

          

       设置了不同的属性,产生了不一样的变化,Why? 

       接着,我们来看下面的一组数据:(先设置frame,后设置bounds)

2020-08-20 16:29:35.173101+0800 FrameAndBoundsDemo[41016:1248335] 
原始frame:(100, 100, 100, 100),原始bounds:(0, 0, 100, 100),原始center:(150,150)
输出frame:{{100, 100}, {100, 100}},输出bounds:{{0, 0}, {100, 100}},输出center:{150, 150}

2020-08-20 16:32:50.221082+0800 FrameAndBoundsDemo[41057:1250415] 
原始frame:(100, 100, 100, 100),原始bounds:(0, 0, 200, 200),原始center:(150,150)
输出frame:{{50, 50}, {200, 200}},输出bounds:{{0, 0}, {200, 200}},输出center:{150, 150}

2020-08-20 16:34:22.728527+0800 FrameAndBoundsDemo[41072:1251299] 
原始frame:(100, 100, 100, 100),原始bounds:(0, 0, 300, 200),原始center:(150,150)
输出frame:{{0, 50}, {300, 200}},输出bounds:{{0, 0}, {300, 200}},输出center:{150, 150}

2020-08-20 16:39:15.104338+0800 FrameAndBoundsDemo[41129:1254300] 
原始frame:(100, 100, 100, 100),原始bounds:(100, 100, 100, 100),原始center:(150,150)
输出frame:{{100, 100}, {100, 100}},输出bounds:{{100, 100}, {100, 100}},输出center:{150, 150}

2020-08-20 16:44:32.482065+0800 FrameAndBoundsDemo[41155:1256502] 
原始frame:(100, 100, 100, 100),原始bounds:(200, 200, 100, 100),原始center:(150,150)
输出frame:{{100, 100}, {100, 100}},输出bounds:{{200, 200}, {100, 100}},输出center:{150, 150}

2020-08-20 16:45:49.825096+0800 FrameAndBoundsDemo[41173:1257439] 
原始frame:(100, 100, 100, 100),原始bounds:(300, 200, 100, 100),原始center:(150,150)
输出frame:{{100, 100}, {100, 100}},输出bounds:{{300, 200}, {100, 100}},输出center:{150, 150}

       通过这组数据,你发现了什么?

       1、bounds的size(尺寸)改变,会改变frame的origin(起点)和size(尺寸);

       2、无论bounds如何改变,View的中心点都不会改变;

       3、无论bounds的origin(起点)如何改变,都不会改变frame;(这是不是意味着设置bounds的orgin没有用了?你太天真了,存在即合理,接着往下看)

       再来看一个代码示例,只设置A、B、C三个View的frame:

    UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    [viewA setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:viewA];

    UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    [viewB setBackgroundColor:[UIColor yellowColor]];
    [viewA addSubview:viewB];

    UIView *viewC = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    [viewC setBackgroundColor:[UIColor blueColor]];
    [viewB addSubview:viewC];

       效果如下:

       我们可以看出,viewA的父视图是self.view,viewB的父视图是viewA,viewC的父视图是viewB,所以根据位置的展示得出结论:frame是view在父视图坐标系中的起点和大小,以父视图坐标系做为参照点。

       接下来,我们把bounds属性也修改一下:

       测试一:

    viewA.bounds = CGRectMake(50, 50, 200, 200);
    viewB.bounds = CGRectMake(50, 50, 200, 200);
    viewC.bounds = CGRectMake(50, 50, 200, 200);

 

         测试二:

    viewA.bounds = CGRectMake(10, 10, 200, 200);
    viewB.bounds = CGRectMake(20, 20, 200, 200);
    viewC.bounds = CGRectMake(30, 30, 200, 200);

       测试三:

    viewA.bounds = CGRectMake(-10, -10, 200, 200);
    viewB.bounds = CGRectMake(-20, -20, 200, 200);
    viewC.bounds = CGRectMake(-30, -30, 200, 200);

       经过三个测试数据,我们来分析一下,

       测试一,viewA是以self.view为父视图,父视图的坐标系bounds是(0,0)开始,所以viewA的位置frame在(50,50);viewB是以viewA为父视图,父视图的坐标系bounds是以(50,50)为原点开始的,所以viewB的位置frame(50,50)在坐标系原点,所以viewB和viewA重合了;同理,viewC是以viewB为父视图,父视图的坐标系bounds是以(50,50)为原点开始的,所以viewC的位置frame(50,50)在坐标系原点,所以viewC和viewB重合了。

       测试二,测试三,同理测试一的分析,可得出显示的结果,于是,我们可以得出结论:每个视图都有自己的坐标系,且这个坐标系默认以自身的左上角为坐标原点,所有子视图以这个坐标系的原点为基准点。bounds的起点代表的是子视图看待当前视图左上角的位置,bounds的大小代表当前视图的大小。更改bounds中的起点对于当前视图没有影响,只是更改了当前视图的坐标系,对于子视图来说当前视图的左上角已经不再是(0,0), 而是改变后的坐标,坐标系改了,那么所有子视图的位置也会跟着改变。更改bounds的大小,bounds的大小代表当前视图的长和宽,修改长宽后,中心点继续保持不变,长宽进行改变,通过bounds修改长宽看起来就像是以中心点为基准点对长宽两边同时进行缩放。

       以上就是对frame和bounds的分析,如果理解的不是很清楚,没关系,你可以这么理解:bounds改变size的大小以frame的中心点向外扩大或缩小是因为,frame确定了view的位置,那么中心点的位置就是固定的,所以即使改变了bounds的大小,还是以frame的中心点,向外扩大或缩小。frame确定位置,bounds改变大小,从而增加点击范围,之后大家可以测试一下改变button的bounds大小,点击范围会不会变大,希望会对你以后的控件开发有所帮助。

       好啦,今天就到这里,如果还不理解,那就多读两边,书读百遍,其义自见。该下班了,代码都在上面,所以Demo就不上传Github了,感谢大家。

       转载请注明出处,编写不易,且行且珍惜~~~



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hbblzjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值