下面来借助于 UITableView+FDTemplateLayoutCell 演示一下 cell 的高度自适应:孙源老师是用xib实现的,我这里用Masonry代码布局来实现。当然,UITableViewHeaderFooterView也是相似用法。
注意点:
- 在 tableView 里,需要对 cell 进行注册
(必须)
- 在 tableView 里,需要对 cell 进行注册
// xib
- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier;
// 纯代码
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier;
- 返回 cell 的高度的三种方法
// 返回由重用标识符指定并由 block 配置的类型的 cell 高度。
- (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier configuration:(void (^)(id cell))configuration;
// 该方法和`-fd_heightForCellWithIdentifier:configuration`做一样的事,
// 计算的高度将由其 indexPath 缓存,需要时返回缓存的高度。
// 因此,能节省很多高度计算。
// 无需担心数据源改变导致 cell 高度无效的问题,`-reloadData`或任意触发tableview重载都会重新计算
- (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier cacheByIndexPath:(NSIndexPath *)indexPath configuration:(void (^)(id cell))configuration;
// 该方法通过模型实体的标识符缓存高度。
// 如果您的模型已更改,请调用“-invalidateHeightForKey:(id <NSCopying>)key”以使缓存无效并重新计算,
// 它比“cacheByIndexPath”更高效。
- (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier cacheByKey:(id<NSCopying>)key configuration:(void (^)(id cell))configuration;
以下为代码:
DetailViewController.h
#import "DetailViewController.h"
#import "FeedEntity.h"
#import "DetailTableViewCell.h"
#import "UITableView+FDTemplateLayoutCell.h"
@interface DetailViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *mTableView;
@property (nonatomic, strong) NSMutableArray *dataList;
@end
static NSString *cellIdentifier = @"UITableViewCell";
@implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.mTableView registerClass:[DetailTableViewCell class] forCellReuseIdentifier:cellIdentifier];
[self fetchDataFromLocalJSON];
}
#pragma mark - tableViewDataSource && tableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.dataList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DetailTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(DetailTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2 == 0) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
cell.entity = self.dataList[indexPath.row];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [tableView fd_heightForCellWithIdentifier:cellIdentifier cacheByIndexPath:indexPath configuration:^(DetailTableViewCell *cell) {
[self configureCell:cell atIndexPath:indexPath];
}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void)fetchDataFromLocalJSON {
NSString *dataFilePath = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:dataFilePath];
NSDictionary *rootDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *feedDicts = rootDict[@"feed"];
NSMutableArray *entities = @[].mutableCopy;
[feedDicts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[entities addObject:[[FeedEntity alloc] initWithDictionary:obj]];
}];
self.dataList = entities;
}
#pragma mark - Getters
- (NSMutableArray *)dataList {
if (!_dataList) {
_dataList = [NSMutableArray array];
}
return _dataList;
}
@end
DetailTableViewCell.h
#import "DetailTableViewCell.h"
//Libs
#import "UILabel+MZExtension.h"
#import <Masonry/Masonry.h>
//Model
#import "FeedEntity.h"
@interface DetailTableViewCell ()
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *contentLabel;
@property (nonatomic, strong) UIImageView *contentImageView;
@property (nonatomic, strong) UILabel *usernameLabel;
@property (nonatomic, strong) UILabel *timeLabel;
@end
@implementation DetailTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self buildViews];
}
return self;
}
- (void)setEntity:(FeedEntity *)entity {
_entity = entity;
self.titleLabel.text = entity.title;
self.contentLabel.text = entity.content;
self.contentImageView.image = entity.imageName.length > 0 ? [UIImage imageNamed:entity.imageName] : nil;
self.usernameLabel.text = entity.username;
self.timeLabel.text = entity.time;
}
- (void)buildViews {
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.contentLabel];
[self.contentView addSubview:self.contentImageView];
[self.contentView addSubview:self.usernameLabel];
[self.contentView addSubview:self.timeLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.equalTo(@10);
make.right.equalTo(@-20);
make.height.equalTo(@17).priorityHigh();
}];
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.titleLabel);
make.height.greaterThanOrEqualTo(@17);
make.top.equalTo(self.titleLabel.mas_bottom).offset(10);
}];
[self.contentImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentLabel.mas_bottom).offset(10).priorityHigh();
make.left.equalTo(self.titleLabel);
make.bottom.equalTo(self.usernameLabel.mas_top).offset(-10);
make.right.lessThanOrEqualTo(@-16);
}];
[self.usernameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.titleLabel);
make.size.equalTo(self.usernameLabel);
make.bottom.equalTo(@-15);
}];
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(@-20);
make.centerY.equalTo(self.usernameLabel);
make.size.equalTo(self.timeLabel);
}];
}
#pragma mark - Getters
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [UILabel labelWithTitle:@"名字" color:@"00006C" fontSize:17];
}
return _titleLabel;
}
- (UILabel *)contentLabel {
if (!_contentLabel) {
_contentLabel = [UILabel labelWithTitle:@"名字" color:@"555555" fontSize:15];
_contentLabel.numberOfLines = 0;
}
return _contentLabel;
}
- (UILabel *)usernameLabel {
if (!_usernameLabel) {
_usernameLabel = [UILabel labelWithTitle:@"名字" color:@"AAAAAA" fontSize:13];
}
return _usernameLabel;
}
- (UILabel *)timeLabel {
if (!_timeLabel) {
_timeLabel = [UILabel labelWithTitle:@"名字" color:@"8CAAE4" fontSize:13];
}
return _timeLabel;
}
- (UIImageView *)contentImageView {
if (!_contentImageView) {
_contentImageView = [[UIImageView alloc] init];
}
return _contentImageView;
}
@end
FeedEntity.h
#import <Foundation/Foundation.h>
@interface FeedEntity : NSObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@property (nonatomic, copy, readonly) NSString *identifier;
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSString *content;
@property (nonatomic, copy, readonly) NSString *username;
@property (nonatomic, copy, readonly) NSString *time;
@property (nonatomic, copy, readonly) NSString *imageName;
@end
FeedEntity.m
#import "FeedEntity.h"
@implementation FeedEntity
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
self = super.init;
if (self) {
_identifier = [self uniqueIdentifier];
_title = dictionary[@"title"];
_content = dictionary[@"content"];
_username = dictionary[@"username"];
_time = dictionary[@"time"];
_imageName = dictionary[@"imageName"];
}
return self;
}
- (NSString *)uniqueIdentifier {
static NSInteger counter = 0;
return [NSString stringWithFormat:@"unique-id-%@", @(counter++)];
}
@end









网友评论