您的位置:首页 > 移动开发 > IOS开发

iOS开发之NSLayoutConstraint

2016-01-10 09:38 489 查看
AutoLayout是从IOS 6开始苹果引入来取代autoresizing的新的布局技术。使用NSLayoutConstraint对view进行布局,就不需要计算view的frame。引入该约束API是为了更好的做一些屏幕适配的工作。

在使用NSLayoutConstraint之前需要知道以下两点:

必须设置 translatesAutoresizingMaskIntoConstraints为NO。
如果是viewControl则AutoLayout适配写在[- updateViewConstraints]中;如果是view则AutoLayout适配写在[- updateConstraints]中。
NSLayoutConstraint是将约束添加到父控件中。

下面来简单的使用NSLayoutConstraint。首先创建两个view(redView, blueView)

- (void)viewDidLoad
{
[super viewDidLoad];

// 红色view
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
self.redView = redView;
// 首先禁用UIViewAutoresizing
self.redView.translatesAutoresizingMaskIntoConstraints = NO;

// 蓝色view
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
self.blueView = blueView;
// 首先禁用UIViewAutoresizing
self.blueView.translatesAutoresizingMaskIntoConstraints = NO;

}


下面只对redView相对于父控件self.view进行布局,确定redView的位置和尺寸方法很多,这里只是其中一种。

/**
*  redView相对于父控件布局
*/
- (void)testConstraint1 {

// 开始对redView进行布局:NSLayoutConstraint
// NSLayoutConstraint使用公式:item.attribute = item.attribute * multi + constant
// redView的顶部约束
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:-10];

// redView的左部约束
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:-10];

// redView的高度约束
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:100];

// redView的右部约束
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:10];

// 设置redView的约束
[self.view addConstraints:@[topConstraint, leftConstraint, heightConstraint, rightConstraint]];
}


横竖屏效果:





上面介绍的是子控件相对于父控件的布局,下面介绍两个子控件之间的相对约束,并设置redView高度约束的优先级。

/**
*  blueView相对于redView进行布局
*/

- (void)testConstraint2 {

// 开始对redView进行布局:NSLayoutConstraint
// NSLayoutConstraint使用公式:item.attribute = item.attribute * multi + constant
// redView的顶部约束
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.redView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:50];

// redView的左部约束
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.redView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:50];

// redView的宽度约束
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.redView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:-100];

// 设置高度最小200约束
NSLayoutConstraint *lessH = [NSLayoutConstraint constraintWithItem:self.redView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationGreaterThanOrEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:200];

// 设置高度优先级
lessH.priority = UILayoutPriorityDefaultHigh;

// 设置redView的约束
[self.view addConstraints:@[topConstraint, leftConstraint, widthConstraint, lessH]];

// 开始对blueView进行布局:NSLayoutConstraint
// NSLayoutConstraint使用公式:item.attribute = item.attribute * multi + constant
// blueView的顶部约束
NSLayoutConstraint *bTopConstraint = [NSLayoutConstraint constraintWithItem:self.blueView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:50];

// blueView的左部约束
NSLayoutConstraint *bLeftConstraint = [NSLayoutConstraint constraintWithItem:self.blueView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0];

// blueView的宽度约束
NSLayoutConstraint *bWidthConstraint = [NSLayoutConstraint constraintWithItem:self.blueView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.redView
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];

// blueView的高度约束
NSLayoutConstraint *bHeightConstraint = [NSLayoutConstraint constraintWithItem:self.blueView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.0
constant:100];

// 设置blueView的约束
[self.view addConstraints:@[bTopConstraint, bLeftConstraint, bWidthConstraint, bHeightConstraint]];
}


横竖屏效果:





使用NSLayoutConstraint对控件布局减少了计算frame的麻烦,不过从上面的代码可以看出来,要对一个控件进行简单的约束代码量还是很大的,不过这也是没有办法。

我们如何在NSLayoutConstraint布局中设置控件的动画和frame的改变呢?

要平移某个控件
对某个控件进行缩放

平移:找到对应的约束条件,去改变它的常量constant,如下点击控制器view将redView向下平移

/**
*  查找一个试图中制定的约束contraint
*
*  @param view     被查找的试图
*  @param constant 常量
*/
- (void)replaceView:(UIView *)view topConstraintWithConstant:(CGFloat)constant
{
// 遍历view上的所有约束
for (NSLayoutConstraint *constraint in view.superview.constraints) {

// 符合条件的约束
if (constraint.firstItem == view
&& constraint.firstAttribute == NSLayoutAttributeTop
) {

// 执行动画
[UIView animateWithDuration:2.0 animations:^{

constraint.constant += constant;
[self.view layoutIfNeeded];// 重新布局
}];
}
}
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

// 平移
[self replaceView:self.redView topConstraintWithConstant:200];

}
缩放:找到对应的约束条件,移除该约束条件,再添加一个新的约束条件

- (void)performAnimatView:(UIView *)view {
// 遍历view上的所有约束
for (NSLayoutConstraint *constraint in view.superview.constraints) {

// 符合条件的约束
if (constraint.firstItem == view
&& constraint.firstAttribute == NSLayoutAttributeWidth
) {

// 移除该约束条件
[self.view removeConstraint:constraint];

// 添加新的约束条件,并执行动画
[UIView animateWithDuration:2.0 animations:^{

NSLayoutConstraint *cw = [NSLayoutConstraint constraintWithItem:self.redView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:-200];
[self.view addConstraint:cw];

[self.view layoutIfNeeded];// 重新布局
}];
}
}

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

// 缩放
[self performAnimatView:self.redView];

}


注意:当修改一个view的约束的时候,其他相对于该view布局的视图都会跟着改变约束。

太累了。这些代码太繁琐了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: