动态添加子视图 UIView 的正确方法
很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict。
但小牛哥最近发现很多新人都不太清楚正确的使用方法,以下是哥的一些总结,有何不妥欢迎大家一起讨论:
(前提条件是这样的:有一个 View Controller 和相应的 xib 文件,我们需要为这个controller 动态加上其他的子视图)
UIViewController 中动态添加 UIView 正确的步骤应该是:
1. 在 viewDidLoad 中创建要添加的 UIView (UILabel, UIImageView, UIButton 等等)。像这样: UIButton *aButton = [[UIButton alloc] initWithFrame:…] 为什么不能在 viewWillAppear 中创建?根据苹果的文档,这里是添加 last minute 修改的地方,比如修改视图的位置,颜色等等。如果在这里创建很多视图,会导致显示延迟。
2. 创建的时候最好为每个 UIView 加上约束(NSLayoutConstraint),这样在不同大小的屏幕中都可以正确显示。
3. 不用约束也行,必须在 viewDidLayoutSubviews 中修改视图的 frame。
对于一些简单的视图确实没必要加上约束,但是没有约束会导致视图在不同大小的屏幕中的 frame 不好看,这时就得在这里修改 frame, 对,只能在这里: viewDidLayoutSubviews 里修改。
为什么呢?
首先咱来复习一下 UIViewController 的生命周期:
A: init…
B: loadView
C: viewDidLoad
D: viewWillAppear
E: viewWillLayoutSubviews
F: viewDidLayoutSubviews
G: viewDidAppear
H: viewWillDisappear
I: viewDidDisappear
J: viewDidUnload (not used any more)
K: dealloc…
现在咱可以做个实验: 在项目中选一个View Contorller ,它的 xib 中的视图大小为 600×600, 在其 .m 文件中以上的 C, D,E,F,G方法打印出视图的frame,像这样:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"%s self.view.frame: %@", __PRETTY_FUNCTION__, NSStringFromCGRect(self.view.frame));
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%s self.view.frame: %@", __PRETTY_FUNCTION__, NSStringFromCGRect(self.view.frame));
}
-(void)viewWillLayoutSubviews
{
NSLog(@"%s self.view.frame: %@", __PRETTY_FUNCTION__, NSStringFromCGRect(self.view.frame));
}
-(void)viewDidLayoutSubviews
{
NSLog(@"%s self.view.frame: %@", __PRETTY_FUNCTION__, NSStringFromCGRect(self.view.frame));
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%s self.view.frame: %@", __PRETTY_FUNCTION__, NSStringFromCGRect(self.view.frame));
}
选择设备为 iPhone 5, 运行程序后会得到类似这样的结果:
[TaskDetailsViewController viewDidLoad] self.view.frame: {{0, 0}, {600, 600}}
[TaskDetailsViewController viewWillAppear:] self.view.frame: {{0, 0}, {600, 600}}
[TaskDetailsViewController viewWillLayoutSubviews] self.view.frame: {{0, 0}, {320, 568}}
[TaskDetailsViewController viewDidLayoutSubviews] self.view.frame: {{0, 0}, {320, 568}}
[TaskDetailsViewController viewDidAppear:] self.view.frame: {{0, 0}, {320, 568}}
大家可以看到,一个视图的大小是在调用 viewWillLayoutSubviews 时才会根据设备而改变,不过在 IOS 8 中,要到viewDidLayoutSubviews 才正确。根视图的大小改变了,子视图必须相应做出调整才可以正确显示,这就是为什么要在 viewDidLayoutSubviews 中调整动态视图的frame。
By the way,在 IOS 9 中,根视图控件(Root View Controller)的视图大小在 viewDidLoad 中就已经正确了,苹果好像会不时改变这些特点,比如会把系统键盘的视图优先级提高等等。所以小牛哥觉得动态添加视图最安全的方法是,创建视图后马上加上约束,不管日后苹果怎么改都可以正确显示。
关于如何动态添加约束,大家可以看看这里:
http://matthewmorey.com/creating-uiviews-programmatically-with-auto-layout/
动态添加子视图 UIView 的正确方法的更多相关文章
- 【iOS开发】动态添加子视图 UIView 的正确方法
很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict. 但小牛哥最近发现很多新人都不太清楚正确的使用方法 ...
- 关于cell中添加子视图 复用重叠问题的解决方法
问题本质: 因为你要添加的子视图并不是在自定义的cell中实现的,而是根据系统给的UITableViewCell这个类创建的实例,每次进图 cellForRow方法都会创建一个cell,每次都要创 ...
- iOS开发-在表单元中添加子视图
#import <UIKit/UIKit.h> @interface NameAndColorCellTableViewCell : UITableViewCell @property(c ...
- C#主菜单动态添加子菜单并设置触发事件
我所使用的是devxepress中的主菜单栏时barsubitem控件,想的是在其能够动态添加子菜单栏并能点击触发事件: /// <summary> /// 创建主按钮的子按钮 /// & ...
- UIView 添加子视图的常用方法
1. - (void)addSubview:(UIView *)view 这是最常用的方法有两个注意点 参数view可以是nil,运行不会报错,当然,父视图的subViews也不会增加. 此方法增加 ...
- 获取XIB子视图的两个方法
创建了一个XIB文件 CommentCell.xib,并设置好UIImageView的tag为100,昵称UILabel的tag为101,时间的UILabel的tag为102,并制定cell为Comm ...
- Android 添加子视图(addView和setView)
我们在添加视图文件的时候有两种方式,一种是通过在xml文件定义layout,另一种方式是在java代码中动态生成布局文件. 在xml中定义的layout要想转化为view,需要使用到LayoutInf ...
- jQuery给动态添加的元素绑定事件的方法
我们在开发过程会遇到无法给动态元素添加绑定事件,解决方案如下: 例如 <div id="testdiv"> <ul></ul> </d ...
- macOS 中使用 phpize 动态添加 PHP 扩展的错误解决方法
使用 phpize 动态添加 PHP 扩展是开发中经常需要做的事情,但是在 macOS 中,首次使用该功能必然会碰到一些错误,本文列出了这些错误的解决方法. 问题一: 执行 phpize 报错如下: ...
随机推荐
- 使用Markdown在博客里插入代码
今天尝试了一下在线使用Markdown编辑器写博客,发现想要实现下面这样的效果还真得折腾一会儿. <html> <head> <meta charset="ut ...
- matlab常用小函数(一)
(第1维为对每一列操作,第2维维对每一行操作) sum 求和操作 max 求最大值操作 sum:求和操作 sum(A):矩阵A按列向求和(每一列求和),结果为一个行向量 sum(A,2):矩阵A按行向 ...
- 你一定要知道的关于Linux文件目录操作的12个常用命令
写在前面: 1,<你一定要知道的关于Linux文件目录操作的12个常用命令>是楼主收集的关于Linux文件目录操作最常用的命令,包括文件或目录的新建.拷贝.移动.删除.查看等,是开发人员操 ...
- 【技术贴】解决xp下Microsoft.SqlServer.Management.PSProvider.dll
解决 安装SQLserver2008时有出错信息,提示:Configuration error description: 无法获得 C:\Program Files\Microsoft SQL Ser ...
- C语言中.h和.c文件解析
整理自C语言中.h和.c文件解析(很精彩) Part.1(林锐<高质量C/C++编程>) 通过头文件来调用库功能.在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的 ...
- druid配置(转)
java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,有不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色的性能,也 ...
- View的getLeft, getRight, getTop, getBottom
View的getLeft, getRight, getTop, getBottom方法得到的分别是相对于其父组件原点坐标不同方向的距离 网上找了张图说明: 其中right和left的计算方法如下: r ...
- bzoj1297
首先学习是学习矩阵乘法在邻接矩阵的应用ab两点经过k条边的路径数就等于图的邻接矩阵G的k次幂之后G[a,b]的值但这道题问的是经过长度为k的路径数考虑到每条边的长度最长只有9,所以我们把一个点拆成9个 ...
- C/S结构与B/S结构的特点分析
C/S结构与B/S结构的特点分析 为了区别于传统的C/S模式,才特意将其称为B/S模式.认识到这些结构的特征,对于系统的选型而言是很关键的. 1.系统的性能 在系统的性能方面,B/S占有优势的是其异地 ...
- java 对list进行排序
前提: list中的元素是自定义对象,如何根据对象的元素进行排序呢? 比如List<Student>students 是一个list,每个元素都是Student对象,Student对象中有 ...