博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 常用布局方式之Constraint
阅读量:7197 次
发布时间:2019-06-29

本文共 5187 字,大约阅读时间需要 17 分钟。

级别: ★★☆☆☆

标签:「iOS AutoLayout」「iOS 自动布局」「NSLayoutConstraint」
作者: 
审校:

在 线下分享时,有和前端同学讨论到iOS的常用布局方式。讨论过程十分热闹,不容易记录,但作者认为讨论结果有必要记录一下,希望能帮助到一些同学。 作者将iOS常用布局方式归纳为Frame、Autoresizing、Constraint、StackView和Masonry五种,并将逐一介绍。 本篇文章介绍Constraint。

Constraint相较于Autoresizing要更加灵活和强大,可以说是一种替代方案。Constraint的全称是NSLayoutConstraint,也常被称作AutoLayout,配合着Storyboard可以非常方便地构建页面。比如作者在中没有实现的同级视图之间约束问题,使用NSLayoutConstraint将迎刃而解,并且不需要编写代码。在Storyboard中构建的约束关系如下。

当然,开发者也可以使用代码的形式利用NSLayoutConstraint布局视图。比如,作者在4等分视图的基础上,在浅灰色contentView上添加一个藏青色(cyanColor)的subView5,使其始终以固定的宽高居中显示,也就是实现下图中的效果。

实现上述效果的代码如下。

- (void)viewDidLoad {        [super viewDidLoad];        UIView *subView5 = [[UIView alloc] initWithFrame:CGRectZero];    subView5.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:.6];    subView5.translatesAutoresizingMaskIntoConstraints = NO;    [_contentView addSubview:subView5];        NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:100.0];    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200.0];    NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:.0];    NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:subView5 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_contentView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:.0];        [_contentView addConstraints:@[widthConstraint, heightConstraint, centerXConstraint, centerYConstraint]];}复制代码

通过上述代码,看一下NSLayoutConstraint的用法。 首先,在使用代码利用NSLayoutConstraint布局视图时,要先指明该视图不被Autoresizing所控制(代码如下)。否则,会出现约束冲突的情况。

subView5.translatesAutoresizingMaskIntoConstraints = NO;复制代码

然后,约束视图是通过“设定约束”和“添加约束”两个步骤来完成的。

设定约束

NSLayoutConstraint有标准的API来设定约束,如下。

/* Create constraints explicitly.  Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant"  If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute. */+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;复制代码

通俗地解释一下上面的API:对view1的attr1属性和view2的attr2属性以relation这种关系和multiplier这种倍数进行c数值的约束。 比如,约束view1和view2等宽可以这样写:

[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeWidth multiplier:1.0 constant:.0];复制代码

其中,attr1和attr2都是从NSLayoutAttribute枚举中取值。

typedef NS_ENUM(NSInteger, NSLayoutAttribute) {    NSLayoutAttributeLeft = 1,    NSLayoutAttributeRight,    NSLayoutAttributeTop,    NSLayoutAttributeBottom,    NSLayoutAttributeLeading,    NSLayoutAttributeTrailing,    NSLayoutAttributeWidth,    NSLayoutAttributeHeight,    NSLayoutAttributeCenterX,    NSLayoutAttributeCenterY,    NSLayoutAttributeLastBaseline,    NSLayoutAttributeBaseline NS_SWIFT_UNAVAILABLE("Use 'lastBaseline' instead") = NSLayoutAttributeLastBaseline,    NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0),        NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),    NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),        NSLayoutAttributeNotAnAttribute = 0};复制代码

relation是从NSLayoutRelation枚举中取值。

typedef NS_ENUM(NSInteger, NSLayoutRelation) {    NSLayoutRelationLessThanOrEqual = -1,    NSLayoutRelationEqual = 0,    NSLayoutRelationGreaterThanOrEqual = 1,};复制代码

综上,在理解API各参数含义的基础上将会更容易读懂上述subView5的4个约束。

添加约束

先看一下例子中添加约束的代码,如下。

[_contentView addConstraints:@[widthConstraint, heightConstraint, centerXConstraint, centerYConstraint]];复制代码

作者将4个约束都添加到了contentView上面,当然,运行效果证明这样添加没有问题。但有的同学问道:“ 因为subView5的位置被约束到了contentView上,所以centerXConstraint和centerYConstraint被添加到contentView上是容易被理解的,但是widthConstraint和heightConstraint只和subView5有关系,为什么也添加到了contentView上,不是应该添加到subView5上吗?”。是的,按照这种说法,widthConstraint和heightConstraint添加到subView5的确更容易理解,于是作者做了如下修改。

[subView5 addConstraints:@[widthConstraint, heightConstraint]];[_contentView addConstraints:@[centerXConstraint, centerYConstraint]];复制代码

从修改后的运行效果看也是没有问题的。之所以将4个constraint都添加到了contentView上,是因为**不管是对哪个视图的约束,只要添加到该视图或者该视图的父视图以及更高层级的父视图上,都是没有问题的。**所以,在编程中,开发者常常会将多个约束统一添加到某个比较靠近用户的父视图上。

关于本篇文章的具体实现细节可以在中查看。


小编微信:可加并拉入《QiShare技术交流群》。

关注我们的途径有:

QiShare(微信公众号)

推荐文章:

转载于:https://juejin.im/post/5cf4f35fe51d45599e019d62

你可能感兴趣的文章
【Java学习笔记】TCP客户端/服务器端
查看>>
LVS三种模式与八种调度算法
查看>>
WPF跑GIF文件的方法
查看>>
SEO独家揭秘:搜索引擎如何识别链接作弊!
查看>>
gzip压缩js和html文件java源码
查看>>
封装的变化之不断变化的需求
查看>>
一个简单的代码生成器(T4文本模板运用)
查看>>
机器学习基石--学习笔记01--linear hard SVM
查看>>
爪哇国新游记之十二----线程创建的两种形式
查看>>
面试题解(1):单向链表相关
查看>>
Qt一步一步实现插件调用(附源码)
查看>>
Ext.grid.CheckboxSelectionModel状态设置
查看>>
IIS负载均衡(转)
查看>>
[原创]用C#实现微信“跳一跳”小游戏的自动跳跃助手
查看>>
Presentation–Introduction
查看>>
【软件】图文解释XCode常用快捷键的使用
查看>>
c# 实现文件浏览功能
查看>>
Linux 小知识翻译 - 「cron」
查看>>
synchronized关键字,Lock接口以及可重入锁ReentrantLock
查看>>
wait、notify、notifyAll的阻塞和恢复
查看>>