iOS Masonry的使用需要注意的地方
自动布局最重要的是约束:UI元素间关系的数学表达式。约束包括尺寸、由优先级和阈值管理的相对位置。它们是添加剂,可能导致约束冲突 、约束不足造成布局无法确定 。这两种情况都会产生异常。
使用前:AutoLayout关于更新的几个方法的区别
setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。layoutSubviews:系统重写布局setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始updateConstraintsIfNeeded:告知立刻更新约束updateConstraints:系统更新约束
使用
1. 基本使用
mas_makeConstraints:添加约束mas_updateConstraints:更新约束、亦可添加新约束mas_remakeConstraints:重置之前的约束multipler属性表示约束值为约束对象的乘因数,dividedBy属性表示约束值为约束对象的除因数,可用于设置view的宽高比
// 进行屏幕的适配的时候,往往需要根据屏幕宽度来适配一个相应的高度,在此推荐使用如下约束的方式来进行控件的适配
[self.topView addSubview:self.topInnerView];
[self.topInnerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(self.topView.mas_height).dividedBy(3);
make.width.and.height.lessThanOrEqualTo(self.topView);
make.width.and.height.equalTo(self.topView).with.priorityLow();
make.center.equalTo(self.topView);
}];
priorityLow()设置约束优先级#define MAS_SHORTHAND_GLOBALS使用全局宏定义,可以使equalTo等效于mas_equalTo#define MAS_SHORTHAND使用全局宏定义, 可以在调用masonry方法的时候不使用mas_前缀
// 这里注意到一个地方,就是当使用了这个全局宏定义之后,发现可以有个类`NSArray+MASAdditions.h`,看了之后发现可以
self.buttonViews = @[ raiseButton, lowerButton, centerButton ];
// 之后可以在updateConstraints 方法中
- (void)updateConstraints {
[self.buttonViews updateConstraints:^(MASConstraintMaker *make) {
make.baseline.equalTo(self.mas_centerY).with.offset(self.offset);
}];
[super updateConstraints];
}
动态修改视图约束:
// 创建视图约束
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
self.animatableConstraint = make.edges.equalTo(superview).insets(paddingInsets).priorityLow();
]];
// 更改约束 (另一处方法中)
UIEdgeInsets paddingInsets = UIEdgeInsetsMake(padding, padding, padding, padding);
self.animatableConstraint.insets = paddingInsets;
[self layoutIfNeeded];
debug模式:// 对某个view添加key值
greenView.mas_key = @"greenView";
// 或者如下顺序
MASAttachKeys(greenView, redView, blueView, superview);
// 同样的对每条约束亦可以添加key
make.height.greaterThanOrEqualTo(@5000).key(@"ConstantConstraint");preferredMaxLayoutWidth: 多行label的约束问题
// 已经确认好了位置
// 在layoutSubviews中确认label的preferredMaxLayoutWidth值
- (void)layoutSubviews {
[super layoutSubviews];
// 你必须在 [super layoutSubviews] 调用之后,longLabel的frame有值之后设置preferredMaxLayoutWidth
self.longLabel.preferredMaxLayoutWidth = self.frame.size.width-100;
// 设置preferredLayoutWidth后,需要重新布局
[super layoutSubviews];
}
scrollView使用约束的问题:原理通过一个contentView来约束scrollView的contentSize大小,也就是说以子控件的约束条件,来控制父视图的大小
// 1. 控制scrollView大小(显示区域)
[self.scrollView makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
// 2. 添加一个contentView到scrollView,并且添加好约束条件
[contentView makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
// 注意到此处的宽度约束条件,这个宽度的约束条件是比添加项
make.width.equalTo(self.scrollView);
}];
// 3. 对contentView的子控件做好约束,达到可以控制contentView的大小
- 新方法:2个或2个以上的控件等间隔排序
/**
* 多个控件固定间隔的等间隔排列,变化的是控件的长度或者宽度值
*
* @param axisType 轴线方向
* @param fixedSpacing 间隔大小
* @param leadSpacing 头部间隔
* @param tailSpacing 尾部间隔
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
withFixedSpacing:(CGFloat)fixedSpacing l
eadSpacing:(CGFloat)leadSpacing
tailSpacing:(CGFloat)tailSpacing;
/**
* 多个固定大小的控件的等间隔排列,变化的是间隔的空隙
*
* @param axisType 轴线方向
* @param fixedItemLength 每个控件的固定长度或者宽度值
* @param leadSpacing 头部间隔
* @param tailSpacing 尾部间隔
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
withFixedItemLength:(CGFloat)fixedItemLength
leadSpacing:(CGFloat)leadSpacing
tailSpacing:(CGFloat)tailSpacing;
使用方法很简单,因为它是NSArray的类扩展:
// 创建水平排列图标 arr中放置了2个或连个以上的初始化后的控件
// alongAxis 轴线方向 固定间隔 头部间隔 尾部间隔
[arr mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:20 leadSpacing:5 tailSpacing:5];
[arr makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@60);
make.height.equalTo(@60);
}];
2. 注意事项
- 约束视图对象只有在被
addSubview之后,才能给视图添加约束 - 当你的所有约束都在
updateConstraints内调用的时候,你就需要在此调用此方法,因为updateConstraints方法是需要触发的
// 调用在view 内部,而不是viewcontroller
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
/**
* 苹果推荐 约束 增加和修改 放在此方法种
*/
- (void)updateConstraints {
[self.growingButton updateConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
make.width.equalTo(@(self.buttonSize.width)).priorityLow();
make.height.equalTo(@(self.buttonSize.height)).priorityLow();
make.width.lessThanOrEqualTo(self);
make.height.lessThanOrEqualTo(self);
}];
//最后记得回调super方法
[super updateConstraints];
}
- 如果想要约束变换之后实现动画效果,则需要执行如下操作
// 通知需要更新约束,但是不立即执行
[self setNeedsUpdateConstraints];
// 立即更新约束,以执行动态变换
// update constraints now so we can animate the change
[self updateConstraintsIfNeeded];
// 执行动画效果, 设置动画时间
[UIView animateWithDuration:0.4 animations:^{
[self layoutIfNeeded];
}];
自动计算UITableViewCell高度
推荐使用一个库UITableView-FDTemplateLayoutCell
想法:动态高度的cell, 主要关注的点是什么?
- viewController本身不需要知道cell的类型
- cell的高度与viewController没有相关性,cell的高度由cell本身来决定
- viewController真正做到的是一个
以下是摘抄过来的
主要是UILabel的高度会有变化,所以这里主要是说说label变化时如何处理,设置UILabel的时候注意要设置 preferredMaxLayoutWidth这个宽度,还有ContentHuggingPriority为 UILayoutPriorityRequried
CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 10 * 2;
textLabel = [UILabel new];
textLabel.numberOfLines = 0;
textLabel.preferredMaxLayoutWidth = maxWidth;
[self.contentView addSubview:textLabel];
[textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(statusView.mas_bottom).with.offset(10);
make.left.equalTo(self.contentView).with.offset(10);
make.right.equalTo(self.contentView).with.offset(-10);
make.bottom.equalTo(self.contentView).with.offset(-10);
}];
[_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
如果版本支持最低版本为iOS 8以上的话可以直接利用UITableViewAutomaticDimension在tableview的heightForRowAtIndexPath直接返回即可。
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 80; //减少第一次计算量,iOS7后支持
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// 只用返回这个!
return UITableViewAutomaticDimension;
}
但如果需要兼容iOS 8之前版本的话,就要回到老路子上了,主要是用systemLayoutSizeFittingSize来取高。步骤是先在数据model中添加一个 height的属性用来缓存高,然后在table view的heightForRowAtIndexPath代理里static一个只初始化一次的Cell实例,然后根据model内容填充数据,最后根 据cell的contentView的systemLayoutSizeFittingSize的方法获取到cell的高。具体代码如下
//在model中添加属性缓存高度
@interface DataModel : NSObject
@property (copy, nonatomic) NSString *text;
@property (assign, nonatomic) CGFloat cellHeight; //缓存高度
@end
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
static CustomCell *cell;
//只初始化一次cell
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])];
});
DataModel *model = self.dataArray[(NSUInteger) indexPath.row];
[cell makeupData:model];
if (model.cellHeight <= 0) {
//使用systemLayoutSizeFittingSize获取高度
model.cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
}
return model.cellHeight;
}
iOS Masonry的使用需要注意的地方的更多相关文章
- iOS masonry九宫格 单行 多行布局
Masonry是个好东西,在当前尺寸各异的iOS开发适配中发挥着至关重要的作用,由于项目中Masonry布局用的比较多,对于UI布局也有了一些自己的理解,经常会有人问道Masonry布局九宫格要怎么布 ...
- iOS:Masonry介绍与使用
Masonry介绍与使用实践:快速上手Autolayout frame----->autoresing------->autoLayout-------->sizeClasses ...
- iOS masonry布局在iOS11/12上正常 iOS9/10却异常
使用masonry布局,可以布局一套,适配所有机型,但是有时候会出现一些比较特殊的情况,每次iOS11上面开发,开发完成之后,在iOS9,iOS10上查看的时候发现布局与iOS11不完全一致,有的高度 ...
- iOS masonry 不规则tagView布局 并自适应高度
在搜索页面经常会有不规则的tag出现,这种tagView要有点击事件,单个tagView可以设置文字颜色,宽度不固定根据内容自适应,高度固定,数量不固定.总高度就不固定.最近对于masonry的使用又 ...
- iOS Masonry控件等比例布局
一.先解释相关API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /** * distribute with fixed spacing * * ...
- IOS Masonry自动布局
之前项目用Frame布局,这个项目登录用了VFL,后来觉得用Masonry,前天布局TableViewCell时用了下 ,觉得还不错. #import "Masonry.h" #i ...
- iOS Masonry 查看更多 收起
Masonry 查看更多 收起效果实现,带动画 demo下载地址: https://github.com/qqcc1388/MasonryDemo
- ios - masonry第三方库使用自动布局(参考:http://www.cocoachina.com/ios/20141219/10702.html)
#import "ViewController.h" #import "Masonry.h" #define kWeakSelf(weakSelf) __wea ...
- iOS Masonry 抗压缩 抗拉伸
约束优先级: 在Autolayout中每个约束都有一个优先级, 优先级的范围是1 ~ 1000.创建一个约束,默认的优先级是最高的1000 Content Hugging Priority: 该优先级 ...
随机推荐
- weblogic 配置了ssl
jingyan.baidu.com/article/72ee561abfe531e16138dfb5.html http://blog.sina.com.cn/s/blog_7ffec3e201019 ...
- 121.Best Time to Buy and Sell Stock---dp
题目链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ 题目大意:给出一串数组,找到差值最大的差 ...
- Ubuntu下安装Sublime Text3
1. 下载软件 Ctrl+Alt+T 调出命令窗口执行下面命令下载安装包: sudo add-apt-repository ppa:webupd8team/sublime-text-3 2. 更新软件 ...
- 构建基于TCP的应用层通信模型
各层的关系如下图,表述的是两个应用或CS间通信的过程: 通常使用TCP构建应用时,需要考虑传输层的通信协议,以便应用层能够正确识别消息请求.比如,一个请求的内容很长(如传文件),那肯定要分多次发送 ...
- ASCII-->Ansi-->Unicode-->UTF8 关于编码 自己的总结
各种不同的编码 无非就是效率 最大化. 我猜测编码的进化流程: ASCII(American Standard Code for Information Interchange)----满足了美国和西 ...
- 深度揭秘阿里移动端高性能动态化方案Weex
2016年Qcon大会首日,阿里巴巴资深总监.淘宝移动平台.阿里百川负责人庄卓然宣布移动端高性能动态化方案Weex即时内测,并将于6月开源.此消息一出,群情汹涌,在座的程序猿.攻城狮们纷纷拿起手机扫码 ...
- print、println的区别
System.out.print("a");——后面没有换行符 System.out.println("b");——后面有换行符 换行符:\r和\n以及\r\n ...
- AndroidStudio升到最新版本(3.1.2)之后
暂时发现的需要大家注意的地方 1.androidstudio3无法导入moudle? 例如:我写了一个简单的项目,需要导入一个第三方的moudle,我导入: 因为AS升级之后,没有突出颜色的变化(变黑 ...
- PhpStorm设置函数注释模板
*设置位置:"Settings"->"file templates"; 如下图,设置头部注释.类注释以及函数注释,时间.用户名.文件名称等随机改变的属性, ...
- hdu4307
好题,详细题解在这里http://blog.csdn.net/weiguang_123/article/details/8077385 这里回顾一下: 当i和j都在一个集合里会产生新的收益,是经典题直 ...