AutoLayout之关于苹果原生约束的探索
来源:互联网 发布:网络捕鱼平台出租代理 编辑:程序博客网 时间:2024/06/04 19:03
AutoLayout(自动布局),在我们的项目中,我更喜欢把它称为约束。iOS实现约束有几种方式:原生约束api、VFL、IB、第三方约束工具(Masonry、UIView+AutoLayout),这里花一点篇幅来讲述苹果原生的约束。
github:https://github.com/yangqingren/LBAutoLayout
NSLayoutConstraint
我们先来阅读以下官方注释:
/* 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;
大概的意思就是view1的约束等于(等于or不超过or不低于)view2的约束的n倍+常量。
- (UILabel *)lbLabel { if (!_lbLabel) { _lbLabel = [[UILabel alloc] init]; _lbLabel.text = @"我是用来测试约束的Label"; _lbLabel.backgroundColor = [UIColor yellowColor]; _lbLabel.translatesAutoresizingMaskIntoConstraints = NO; } return _lbLabel;}- (void)viewDidLoad { [super viewDidLoad]; self.view.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:self.lbLabel]; // 设置label的top等于self.view的top,倍数为1,offset为偏移80 NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.lbLabel relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:80]; // 设置label的left等于self.view的left,倍数为1,offset为偏移80 NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.lbLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:80]; [self.view addConstraints:@[topConstraint, leftConstraint]]; // Do any additional setup after loading the view, typically from a nib.}
可以看到,只要设置label的top约束和left约束,即可完成布局,也就是说,label(button)约束布局时自带宽高,宽高由其text填充,关于这个,我后面再讲。
由于label的这种特性,我们可以使用简单的约束就可以完成以下的这几种布局:
// shadowLabel的right等于lbLabel的left,达到宽度自适应 NSLayoutConstraint *shadowConstraint = [NSLayoutConstraint constraintWithItem:self.shadowLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.lbLabel attribute:NSLayoutAttributeRight multiplier:1 constant:0];
或者
// shadowLabel的top等于lbLabel的bottom,达到高度自适应 NSLayoutConstraint *shadowConstraint = [NSLayoutConstraint constraintWithItem:self.shadowLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.lbLabel attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
当然也可以设置固定长度
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.lbLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150];
补充:关于AutoLayout与Frame的思考
由于给view设置约束的时候,并没有马上生成相应的frame,这会使得如果对使用约束布局的view获取相应的bounds等操作的时候,获取到的只有CGSizeZero,这里提供一些思路与方案:
// 1.使用layoutIfNeeded,让刚刚设置约束的view立即去布局,之后就有对应的size了[view layoutIfNeeded];
// 2.在layoutSubviews里进行获取- (void)layoutSubviews { [super layoutSubviews]; NSLog(@"self.bounds=%@",self.bounds);}// 但是layoutSubviews会多次调用,这里需要十分注意
上面说到label自带宽高,这里拓展讲解一下
UIView都有一个属性,叫做intrinsicContentSize
当label(button) setText的时候,系统根据字体字体大小与长度设置一个满足label的size,此时会触发一个叫intrinsicContentSize的方法,用这个方法,可以对一些不定字符长度的控件进行设置,如以下这个按钮
- (UIButton *)button { if (!_button) { _button = [UIButton buttonWithType:UIButtonTypeCustom]; [_button setTitle:@"Log in" forState:UIControlStateNormal]; _button.layer.cornerRadius = 4; _button.backgroundColor = [UIColor grayColor]; } return _button;}- (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.button]; [self.button mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(self.view); }]; // Do any additional setup after loading the view, typically from a nib.}
你会看到它的size刚好紧贴着text,效果很差,我们可以通过重写intrinsicContentSize方法,满足布局要求
#import "LBSizeButton.h"@interface LBSizeButton ()@end@implementation LBSizeButton-(CGSize)intrinsicContentSize { CGSize size = [super intrinsicContentSize]; return CGSizeMake(size.width + 10 * 2, size.height + 2 * 2);}@end
github:https://github.com/yangqingren/LBAutoLayout
下次有空写一些关于用Masonry进行布局探索的实例
end
- AutoLayout之关于苹果原生约束的探索
- ScrolView的Autolayout约束
- 108.UIView关于布局和约束的方法(AutoLayout)
- IOS开发之读取使用AutoLayout约束的控件Frame
- 关于AutoLayout和代码修改约束
- AutoLayout约束
- AutoLayout之通过代码添加约束
- iOS开发:XIB之AutoLayout添加约束
- XZ_Swift之苹果原生自动布局的使用
- 关于使用Xcode--Editor相关选项建立autoLayout的约束的使用介绍
- 关于使用autolayout约束的界面添加子界面frame改变的问题
- AutoLayout自动布局添加约束的规则
- 谈StoryBoard上AutoLayout的约束动画
- Autolayout约束的代码实现方式-1
- UIScrollView添加AutoLayout约束的坑
- 获取autolayout约束后的控件
- UIScrollView添加AutoLayout约束的坑
- ios-autolayout添加约束的规则
- Mac下Mysql启动异常["ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.so
- Android音频驱动-ASOC之Control Open
- Net-Snmp工具(学习SNMP的工具,开源项目)简单使用
- [shell] 小括号、中括号、大括号
- 002_table标签制作细线表格
- AutoLayout之关于苹果原生约束的探索
- SSH Could not find action or result: /ssh_01/hello.action
- codeforces 851 C (Div#432) Five Dimensional Points
- Mybatis获取插入记录的自增长ID
- 记1
- 如何使用DOS命令通过FTP进行上传和下载
- poj 1080
- 神奇的hello world
- Java多线程共享变量控制