Masonry+FDTemplateLayoutCell 实现Cell自动布局

在经过frame时代的布局计算后,目前进入了autolayout 布局。相对之前frame布局的算算算,autolayout时代则要好的多,只需要计算控件之间的相对距离。因此布局简洁了不少。

传统的用代码设置autolayout十分复杂,因此这里我们使用一款叫做Masonry的开源框架,它封装了IOS原生代码设置约束的方法。使我们能够更简便的使用代码进行autolayout布局。

 下载地址:https://github.com/SnapKit/Masonry。

既然上面已经介绍了用代码设计的框架,这里我们还需要一个根据约束来对cell进行计算高度的框架.FDTemplateLayoutCell.

下载地址https://github.com/forkingdog/UITableView-FDTemplateLayoutCell

好了废话不多说我们开始今天的项目。

实验目的

1.使用masonry 来给一个表格中的cell设置约束。并且使用FDTemplateLayoutCell来对设置好约束的cell进行行高激素啊。

实验效果 

图一  当文本行高度小于头像的高度时。

图二 当文本行高度大于头像的高度时


实现方法。

首先我们创建一个cell,并且使用Masonry进行代码约束设置。代码如下

- (void) setupLayout {

__weaktypeof(self) weakSelf =self;

UIImageView*contentImageView = [[UIImageViewalloc]init];

// contentImageView.contentMode = UIViewContentModeScaleAspectFit;

[self.contentViewaddSubview:contentImageView];

self.imageV= contentImageView;

UIImageView*headImageV = [[UIImageViewalloc]init];

[self.contentViewaddSubview:headImageV];

self.headImageV= headImageV;

UILabel* contentLabel = [[UILabelalloc]init];

contentLabel.font= [UIFontsystemFontOfSize:13.0f];

contentLabel.textColor= [UIColorredColor];

contentLabel.numberOfLines=0;

contentLabel.textAlignment=NSTextAlignmentNatural;

self.contentLabel= contentLabel;

[self.contentViewaddSubview:contentLabel];

[contentImageViewmas_makeConstraints:^(MASConstraintMaker*make) {

make.top.equalTo(weakSelf.contentView.mas_top).offset(0);

make.left.equalTo(weakSelf.contentView.mas_left).offset(0);

make.right.equalTo(weakSelf.contentView.mas_right).offset(0);

//make.height.equalTo(weakSelf.contentView.mas_width).multipliedBy(0.5);

make.bottom.equalTo(headImageV.mas_top).offset(-10);

}];

[headImageVmas_makeConstraints:^(MASConstraintMaker*make) {

make.size.mas_equalTo(CGSizeMake(60,60));

make.left.equalTo(weakSelf.contentView.mas_left).offset(10);

make.top.equalTo(contentImageView.mas_bottom).offset(10);

// make.bottom.equalTo(weakSelf.contentView.mas_bottom).offset(-10);

make.bottom.equalTo(weakSelf.contentView.mas_bottom).offset(-10).priorityMedium(0);

}];

[contentLabelmas_makeConstraints:^(MASConstraintMaker*make) {

make.top.equalTo(contentImageView.mas_bottom).offset(10);

make.left.equalTo(headImageV.mas_right).offset(10);

make.right.equalTo(weakSelf.contentView.mas_right).offset(-10);

make.bottom.equalTo(weakSelf.contentView.mas_bottom).offset(-10).priorityHigh(0);

}];

}

这里要注意的是,我们添加的控件是添加到了cell中的cotentView里面,因此,再进行父类约束设置的时候,就必须用contentView来进行参照,而不是cell中的View. 比如设置一个UIImageView 它的在其父类视图中,上下左右的间距都是0,它在父视图中展示的效果就应该是一个,铺满父视图的视图。但是如果你添加到contentView上面,却用的是View来进行约束参照。约束就不会起作用,FDTemplateLayoutCell也不会计算出准确的高度。

在设置好约束以后,因为这些控件都是木有数据的,所以现在就只有约束,当然,光有约束我们没有数据,所以我们还是看不出来布局效果。

为了让我们看出布局的效果,所以我们就要为这些控件提供一个写入数据的接口。

- (void)setObject:(entity*)object {

_object= object;

[_imageVsetImage:[UIImageimageNamed:@"contentImage"]];

[_headImageVsetImage:[UIImageimageNamed:@"headImage"]];

[_contentLabelsetText:@"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"];

}

这样一来我们的控件里面也有数据了,下面我们就要用FDTemplateLayoutCell来自动计算我们的cell的高度了。

控制器中的实现代码如下。

- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {

returnself.dataArray.count;

}

- (CGFloat) tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {

return[tableViewfd_heightForCellWithIdentifier:@"masoryCell"cacheByIndexPath:indexPathconfiguration:^(masoryCell* cell) {

//配置cell的数据源,和"cellForRow"干的事一致,比如:

cell.object=self.dataArray[indexPath.row];

}]+20;

}

- (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {

masoryCell* cell =[tableViewdequeueReusableCellWithIdentifier:@"masoryCell"forIndexPath:indexPath];

// UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"customeTableViewCell"];

cell.object=self.dataArray[indexPath.row];

returncell;

}

通过FDTemplateLayoutCell 提供的分类方法

[tableViewfd_heightForCellWithIdentifier:@"masoryCell"cacheByIndexPath:indexPathconfiguration:^(masoryCell* cell) {

//配置cell的数据源,和"cellForRow"干的事一致,比如:

cell.object=self.dataArray[indexPath.row];

}];

就可以为我们计算出cell的高度了

这里要注意的是,必须注册我们的设好的cell到talbeView中 ,这样我们才能复用,这些cell.

提示:在使用masonry为cell设置约束的时候,必须在cell初始化的时候实现,不能在写入数据的时候,为cell设置约束。不然会导致计算不出高度。

为了达到上图中的效果。

当Label的行高大于Image头像的时候,Label的设置的约束起作用。当Label小于头像图片的时候,就头像设置的约束起作用。

这里给出的解决办法是设置约束优先级。autoLayout 约束优先级,工作的原理是这样的:如上图中所示:头像的上约束是,相对于大图的底部间隔10的单位,下约束是相对于contentView底部间隔10个单位。同样Label设置的上下约束也是和头像视图是一致的。所以我们这里设置label的下约束优先级高于头像的下约束,这里头像视图的大小是固定是60x60。而Label高度又是不固定的,所以系统先判断,如果label的行高小于或者等于头像视图的时候。系统默认两个视图的下约束不冲突。各自按照设置好的约束进行设置,所以头像视图的高度等于label视图的高度,因此头像视图距cotentView视图底部为10个单位。但是一旦label的高度大于头像视图的高度,则系统判断优先级更高的label视图的下约束生效。所以就让label的下约束生效。因此label的底部距离contentView视图的底部为10个单位。而头像视图的下约束变为距离contentView底部Label的高度 减去 头像视图的高度 再加上10个单位的距离。

本项目下载地址 https://github.com/coderFrankenstain/fdtableviewcell

关注微信公众号获得更多源码


Masonry+FDTemplateLayoutCell 实现Cell自动布局_第1张图片

你可能感兴趣的:(Masonry+FDTemplateLayoutCell 实现Cell自动布局)