Problem:
在xib文件中可以通过拉伸view来改变view controller的view的大小,也即是它的frame属性(在storyboard或者xcode 5.0以上的xib文件中,需要在attributes inspector的simulated metrices一栏把size勾选为freedom)。IB的具体介绍:
The Role of Interface Builder
Interface Builder is an application that you use to graphically construct and configure your application’s windows and views. Using Interface Builder, you assemble your views and place them in a nib file, which is a resource file that stores a freeze-dried version of your views and other objects. When you load a nib file at runtime, the objects inside it are reconstituted into actual objects that your code can then manipulate programmatically.
Interface Builder greatly simplifies the work you have to do in creating your application’s user interface. Because support for Interface Builder and nib files is incorporated throughout iOS, little effort is required to incorporate nib files into your application’s design.
For more information about how to use Interface Builder, see Interface Builder User Guide. For information about how view controllers manage the nib files containing their views, see “Creating Custom Content View Controllers” in View Controller Programming Guide for iOS.
那么,如何通过代码去实现自定义的view的frame呢?
Solution:
Apple提供了View Controller Programming Guide for iOS。首先,去认真读读这个文档了解关于view controller的知识。
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457-CH1-SW1
Discussion:
理解uiviewcontroller对view layout的过程:
When the size of a view controller’s view changes, its subviews are repositioned to fit the new space available to them. The views in the controller’s view hierarchy perform most of this work themselves through the use of layout constraints and autoresizing masks. However, the view controller is also called at various points so that it can participate in the process. Here’s what happens:
The view controller’s view is resized to the new size.
If autolayout is not in use, the views are resized according to their autoresizing masks.
The view controller’s viewWillLayoutSubviews
method is called.
The view’s layoutSubviews
method is called. If autolayout is used to configure the view hierarchy, it updates the layout constraints by executing the following steps:
The view controller’s updateViewConstraints
method is called.
The UIViewController
class’s implementation of the updateViewConstraints
method calls the view’s updateConstraints
method.
After the layout constraints are updated, a new layout is calculated and the views are repositioned.
The view controller’s viewDidLayoutSubviews
method is called.
要改变controller的view的frame,可以在viewwilllayoutsubviews里面修改。在viewdidload,viewwillappear,viewdidappear修改都不会改变constroller view的大小。
Example:
//
// NoNibViewController.m
// Autollayout
//
// Created by fengtao.ft on 14-6-22.
//
#import "NoNibViewController.h"
@interface NoNibViewController ()
@end
@implementation NoNibViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(@"initWithNibName");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear:self.view.frame = [%f,%f,%f,%f]",self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self.view.frame.size.height);
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
NSLog(@"viewDidAppear:self.view.frame = [%f,%f,%f,%f]",self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self.view.frame.size.height);
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"screensize= [%f,%f]",[UIScreen mainScreen].bounds.size.width,[UIScreen mainScreen].bounds.size.height);
NSLog(@"viewDidLoad:self.view.frame = [%f,%f,%f,%f]",self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self.view.frame.size.height);
self.view.backgroundColor = [UIColor lightGrayColor];
[self.view setClipsToBounds:YES];
self.view.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
UIButton *topbutton = [[UIButton alloc] initWithFrame:CGRectMake(100, -60, 80, 80)];
topbutton.backgroundColor = [UIColor greenColor];
[self.view addSubview:topbutton];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 300, 80, 80)];
button.backgroundColor = [UIColor greenColor];
[self.view addSubview:button];
// Do any additional setup after loading the view from its nib.
UIButton *topbtn = [UIButton buttonWithType:UIButtonTypeSystem];
topbtn.backgroundColor = [UIColor greenColor];
topbtn.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:topbtn];
UIButton *buttombtn = [UIButton buttonWithType:UIButtonTypeSystem];
buttombtn.backgroundColor = [UIColor greenColor];
buttombtn.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:buttombtn];
NSDictionary *viewsDic = [NSDictionary dictionaryWithObjectsAndKeys:topbtn, @"topbtn",buttombtn,@"buttombtn", nil];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-20-[topbtn(40)]"
options:0
metrics:nil
views:viewsDic]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-20-[topbtn(40)]"
options:0
metrics:nil
views:viewsDic]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:[buttombtn(40)]-20-|"
options:0
metrics:nil
views:viewsDic]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[buttombtn(40)]-20-|"
options:0
metrics:nil
views:viewsDic]];
}
- (void)viewWillLayoutSubviews
{
[self.view setFrame:CGRectMake(10, 64, 300, 320)];
NSLog(@"viewWillLaytouSubviews:self.view.frame = [%f,%f,%f,%f]",self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self.view.frame.size.height);
}
- (void)viewDidLayoutSubviews
{
NSLog(@"viewWillLaytouSubviews:self.view.frame = [%f,%f,%f,%f]",self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self.view.frame.size.height);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
调试过程输出信息:
2014-06-22 22:29:24.109 Autollayout[3208:70b] initWithNibName
2014-06-22 22:29:24.109 Autollayout[3208:70b] screensize= [320.000000,568.000000]
2014-06-22 22:29:24.109 Autollayout[3208:70b] viewDidLoad:self.view.frame = [0.000000,0.000000,320.000000,568.000000]
2014-06-22 22:29:24.110 Autollayout[3208:70b] viewWillAppear:self.view.frame = [0.000000,0.000000,320.000000,568.000000]
2014-06-22 22:29:24.115 Autollayout[3208:70b] viewWillLaytouSubviews:self.view.frame = [10.000000,64.000000,300.000000,320.000000]
2014-06-22 22:29:24.116 Autollayout[3208:70b] viewWillLaytouSubviews:self.view.frame = [10.000000,64.000000,300.000000,320.000000]
2014-06-22 22:29:24.617 Autollayout[3208:70b] viewDidAppear:self.view.frame = [0.000000,0.000000,320.000000,568.000000]
2014-06-22 22:29:24.618 Autollayout[3208:70b] viewWillLaytouSubviews:self.view.frame = [10.000000,64.000000,300.000000,320.000000]
2014-06-22 22:29:24.619 Autollayout[3208:70b] viewWillLaytouSubviews:self.view.frame = [10.000000,64.000000,300.000000,320.000000]