大佬儿们,我又双叒叕的来了,大家有没有被问到过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了,感谢大家。

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

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

  1. delphi 获取java控件位置_delphi的IdFTP控件函数怎么调用

    RootDir = 要删除的根目录,一般情况下 RemoteDir 与 RootDir 相等} procedure TForm1.FTP_DeleteAllFiles(var idFTP : TIdF ...

  2. 数据回发时,维护ASP.NET Tree控件位置

    ASP.NET2.0提供了一个功能强大的TreeView控件,但是它看起来有一个缺陷:它好像不能够跟踪用户最后选择的一个节点.如果你滚动到第50个节点然后展开该节点,那么当单击链接页面进行回发后,你必 ...

  3. Qt鼠标相对位置、绝对位置、窗口位置、控件位置、控件大小、控件绝对位置

    目录 坐标系 鼠标位置 控件位置 控件的相对位置 控件绝对位置 控件的大小,rect 窗口位置 窗口的大小 窗口绝对位置 窗口相对位置 总结   在Qt界面开发时,有时需要根据鼠标位置,控件位置来确定 ...

  4. html 控件坐标定位,利用JS改变html控件位置

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 利用JS改变html控件位置 我想写一个贪吃蛇小游戏,所以需要完成蛇的自动移动效果,这就需要改变html控件位置.本来我 ...

  5. WPF 获取鼠标屏幕位置、窗口位置、控件位置

    原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT{public int X;public int Y;public POINT(int x, int y){t ...

  6. android控件之间的过渡动画效果,Android - 交换控件位置:基于LayoutParams的瞬间交换与基于ObjectAnimator动画效果交换...

    现需要交换两个控件(本文中是两个RelativeLayout),找到了两个方法: 1.使用LayoutParams改变两个layout的属性,即其相对关系(below等),实现位置的交换,但是并没有交 ...

  7. 【转】关于EASYSIZE宏(动态调整控件位置、大小的宏)

    假设创建的对话框的类名是CMyDlg,具体过程如下: 步骤一:把easysize.h拷贝到CMyDlg项目文件夹中,同时在CMyDlg的.h文件和.cpp文件中加入#include "eas ...

  8. c++ MFC 根据屏幕分辨率变化自动调整控件位置和大小

    在mfc应用程序开发过程中经常遇到应用场景分辨率不同对应窗口的控件相对位置不同,现在通过在给窗口做尺度变换后,原来的控件位置和大小跟着变,导致界面看起来仍然协调,如下: 缩放前: 缩放后 要解决这个问 ...

  9. ESP32 开发笔记(四)LVGL控件学习 ColorPicker 颜色选择器控件

    先看效果,创建一个颜色选择器控件,设置事件回调动态显示当前选择的颜色值 开发板购买链接https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.5 ...

  10. Android Studio 线性布局Linearlayout的控件位置控制l属性Layout_margin失效问题解决

    Android Studio 线性布局Linearlayout的控件位置控制l属性Layout_margin失效问题解决 问题:如layout_marginRight ="50dp" ...

最新文章

  1. 区块链教程Fabric1.0源代码分析Tx(Transaction 交易)一
  2. Wine 1.0 RC2
  3. 20135310陈巧然 20135305姚歌 实验一:开发环境的熟悉
  4. java中什么表示打印_在java中打印对象时会发生什么
  5. 知识力量_网络分析的力量
  6. InnoDB还是MyISAM?
  7. Win7_64位使用32位Mysql配置Mysql Odbc
  8. spring-tool-suite(STS) 创建 spring boot项目
  9. Android PackageManager 详解
  10. Tkinter模拟发送邮箱验证码并在指定时间后验证码过期
  11. 华为荣耀4X的ROOT
  12. 微信卡券的创建、领取、核销
  13. 关于如何用centos7和阿里云服务器去创建一个网站
  14. 国产首发:上海川土微电子数字接口电源数字隔离芯片模拟芯片领导者
  15. 程序员刷简历领导看见很寒心,网友:找工作也要经过你同意?
  16. asp.net 文件下载的五种方式
  17. Cloudflare到底是不是减速器 免费版cf是减速器吗(实际测试)
  18. 计算机整理桌面怎么弄,图文详解如何整理桌面
  19. 开源RISC-V 项目Freedom在Arty-7-100T开发板上的实现
  20. SQL44 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005

热门文章

  1. 【2017-01-09】 资料链接摘录
  2. win7可以运行python_win7安装python开发环境,运行python
  3. 初识Centos7.5
  4. 特朗普对五角大楼云计算合同表示担忧
  5. qcloud.login 登录失败,可能是网络错误或者服务器发生异常的多种解决方法
  6. tp5 上传路径反斜杠的问题 ,反斜杠json_decode函数输出出错的
  7. 开源的微信公众号管理工具
  8. 反映百度引擎权重的身分都有哪些
  9. 新人如何快速融入团队
  10. 【环境保护网】-环保设备_环保设备网_环保产品网_中国环境保护网