动态添加子视图 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/

时间: 2024-12-06 17:35:40

动态添加子视图 UIView 的正确方法的相关文章

iOS自定义alertView,继承自UIView,可以添加子视图,标题图片+文字

自定义alertView,继承自UIView,可以在消息区域添加子视图:addCustomerSubview 标题可以有图片+文字构成, 只支持两个按钮操作 // - 在需要alert的控制器调用 alertView show 方法 CustomAlertView *alertView = [[CustomAlertView alloc] initWithTitle:@"提示" message:@"dylan_lwb_" delegate:self cancelBu

关于cell中添加子视图 复用重叠问题的解决方法

问题本质: 因为你要添加的子视图并不是在自定义的cell中实现的,而是根据系统给的UITableViewCell这个类创建的实例,每次进图 cellForRow方法都会创建一个cell,每次都要创建一个子视图添(button,label之类的)加进去,会给占用很大的内存,所以采用了复 用的方法,但是问题就来了,当cell超出界面,从队列中拿过来复用的时候,其中子视图的内容并没有消除,这样你会原来的基础上再创建一个子视图添加上去 遮住了原来的视图,一般视图都是透明的这样的话就变成了一层层的叠加.

精通IOS-在表单元中添加子视图

#import <UIKit/UIKit.h> @interface NameAndColorCellTableViewCell : UITableViewCell @property(copy,nonatomic) NSString *name; @property(copy,nonatomic) NSString *color; @end NameAndColorCellTableViewCell.h // // NameAndColorCellTableViewCell.m // Tab

新浪微博开发-添加子视图控制器&amp;设置颜色

一.添加子视图控制器 二.设置颜色 设置颜色:两种方法 一种较为繁琐,详见视频 第二种: //设置颜色 self.tabBar.tintColor = UIColor.orangeColor()

iOS开发-自定义重用机制给ScrollerView添加子视图

其实这个问题我很早就想过,只是没有通过去敲代码实现,昨天有人提起,我就巧了一下 不知道大家打印郭tableview:cellforrow中cell初始的次数,也就是重用池中的cell个数,这个是固定的,比如屏幕最多可以显示4个cell那么重用池个数可能为5个6个或者7左右,我就想了如果scrollview去实现,子视图也应该是有一个个数的,那么如何去实现重用池呢?我想到了数组,可变数组,我在loadview中将scrollview的可滑动区域设置为10000,然后给scrollview每隔20个

57.动态添加子View(Java/XML两种方式)

/** * 动态添加子View(Java) */ private View createViewWithJava() { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); LinearLayout view = new LinearLayout(this); view.set

在UIViewController的view上添加子视图不显示

第一种方式:通过代码方式创建视图控制器UIViewController,添加子视图,需要留意创建视图的size,如果是为0是看不到的 第二种方式:xib或storyboard方式创建视图控制器UIViewController,需要留意xib是否与视图变量之间建立的关系,没有建立关系子视图是添加到视图view中,但是就是不能系显示. 如图:

一文带你彻底明白如何实现动态添加子节点及修改子节点属性

? 终于看完了官方的教程,开始用 Cocos Creator 做第一个游戏——<消灭病毒-重力版>(PS:等做完之后会出一个完整的教程,敬请期待┗( ▔, ▔ )┛!),可是第一步就遇到了坑,本来想动态的通过预制件来添加病毒节点,并修改病毒的血量,可是添加节点之后无论如何都不能对节点的属性进行修改,查了半天资料原来是没有获取子节点的组件,白白浪费了两个小时,这就是自学的弊端吧,有一个好的老师真的是太重要了!为了让大家少走弯路,今天写一个 Demo 来教大家如何实现动态添加子节点及修改子节点属性

UIView 添加子视图的常用方法

1.  - (void)addSubview:(UIView *)view 这是最常用的方法有两个注意点 参数view可以是nil,运行不会报错,当然,父视图的subViews也不会增加. 此方法增加的view层级当前是最高的,也就是最靠外. 2.  - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; 父视图的所有的子视图的index默认是从0开始的. index如果赋了负数,执行不会报错,但添加会失败. 如果index值