MVC模式下代码自定义cell(自计算行高)

2015-10-16  本文已影响925人  与佳期

前言

上一篇文章总结了通过xib自定义cell。当cell中的内容不定,cell的高度也就不定。此时就要动态计算cell的高度,也就是采用本篇文章要讲的代码自定义cell中的方式。

本篇文章就以Demo中 图书馆->查找书籍 的界面为例

首先看一下我们最终实现的样子

屏幕快照 2015-10-16 11.57.27.png

通过代码自定义cell

在QueryCell.m中重写initWithStyle: reuseIdentifier:方法(注意:只管创建添加子控件,先不要去管子控件的位置和尺寸)
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 添加内部的子控件
// 1.封面
_image = [[UIImageView alloc] init];
[self.contentView addSubview:_image];

          // 2.书名
          _title = [[UILabel alloc] init];
          _title.numberOfLines = 0;
          [self.contentView addSubview:_title];
    
          // 3.“作者”
          CGFloat authorLabelX = kImageXY + kImageW + kCellBorder;
          CGFloat authorLabelY = kImageXY + 41 + kCellBorder;
          CGFloat authorLabelW = 46;
          CGFloat authorLabelH = kLabelH;
          _authorLabel = [[UILabel alloc] initWithFrame:CGRectMake(authorLabelX, authorLabelY, authorLabelW, authorLabelH)];
          _authorLabel.text = @"作者:";
          _authorLabel.font = [UIFont systemFontOfSize:15];
          [self.contentView addSubview:_authorLabel];
          // 3.作者
          _author = [[UILabel alloc] init];
          [self.contentView addSubview:_author];
    
          // 4.“出版社”
          CGFloat publishLabelX = authorLabelX;
          CGFloat publishLabelY = authorLabelY + authorLabelH + kCellBorder;
          CGFloat publishLabelW = 60;
          CGFloat publishLabelH = kLabelH;
          _publishLabel = [[UILabel alloc] initWithFrame:CGRectMake(publishLabelX, publishLabelY, publishLabelW, publishLabelH)];
          _publishLabel.text = @"出版社:";
          _publishLabel.font = [UIFont systemFontOfSize:15];
          [self.contentView addSubview:_publishLabel];
          // 4.出版社
          _publish = [[UILabel alloc] init];
          [self.contentView addSubview:_publish];
    
          // 5.“索书号”
          CGFloat numberLabelX = kImageXY;
          CGFloat numberLabelY = kImageXY + kImageH + kCellBorder;
          CGFloat numberLabelW = 60;
          CGFloat numberLabelH = kLabelH;
          _numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(numberLabelX, numberLabelY, numberLabelW, numberLabelH)];
          _numberLabel.text = @"索书号:";
          _numberLabel.font = [UIFont systemFontOfSize:15];
          [self.contentView addSubview:_numberLabel];
          // 5.索书号
          _number = [[UILabel alloc] init];
          [self.contentView addSubview:_number];
    
          // 6.“馆藏地”
          CGFloat placeLabelX = kImageXY + numberLabelW + 120;
          CGFloat placeLabelY = numberLabelY;
          CGFloat placeLabelW = 60;
          CGFloat placeLabelH = kLabelH;
          _placeLabel = [[UILabel alloc] initWithFrame:CGRectMake(placeLabelX, placeLabelY, placeLabelW, placeLabelH)];
          _placeLabel.text = @"馆藏地:";
          _placeLabel.font = [UIFont systemFontOfSize:15];
          [self.contentView addSubview:_placeLabel];
          // 6.馆藏地
          _place = [[UILabel alloc] init];
          [self.contentView addSubview:_place];

          // 7.“简介”
          CGFloat descX = kImageXY;
          CGFloat descY = numberLabelY + numberLabelH + kCellBorder;
          CGFloat descW = 80;
          CGFloat descH = kLabelH;
          _descLabel = [[UILabel alloc] initWithFrame:CGRectMake(descX, descY, descW, descH)];
          _descLabel.text = @"图书简介:";
          _descLabel.font = [UIFont systemFontOfSize:15];
          [self.contentView addSubview:_descLabel];
          // 简介
          _desc = [[UILabel alloc] init];
          _desc.numberOfLines = 0;
          [self.contentView addSubview:_desc];
      }
      return self;
  }

注:当存在固定内容时, 在init方法中直接写定内容、计算出高度就好了。而对于需要根据模型数据显示内容的标签暂时alloc,添加到cell的contentView上就好,在后边的setter方法中会计算高度、添加数据。

设置数据的方法
- (void)settingData{
Query *query = _queryFrame.query;

       // 封面
       NSString *imageStr = [query.image stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
       NSURL *url = [NSURL URLWithString:imageStr];
       [_image sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"book.png"]];

       // 2.书名
       _title.text = query.title;
       _title.textColor = [UIColor grayColor];
    
       // 3.作者
       _author.text = query.author;
       _author.textColor = [UIColor grayColor];

       // 4.出版社
       _publish.text = query.publish;
       _publish.textColor = [UIColor grayColor];

       // 5.索书号
       _number.text = query.number;
       _number.textColor = [UIColor grayColor];

       // 6.馆藏地
       _place.text = query.place;
       _place.textColor = [UIColor grayColor];

       // 简介
       _desc.text = query.desc;
       _desc.textColor = [UIColor grayColor];

  }

注:settingData方法中若是直接加载封面图片,界面会卡顿。所以这里采用第三方库SDWebImage中的方法,如果不想使用第三方库,也可以采用下面的多线程方法:
// 封面
_image.image = [UIImage imageNamed:@"book.png"]; // 放置一张加载完成前的默认图片
// 1.获取一个全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.把任务添加到队列中执行
dispatch_async(queue, ^{
// 3.从网络上下载图片
NSURL *urlstr = [NSURL URLWithString: query.image];
NSData *data = [NSData dataWithContentsOfURL:urlstr];
UIImage *image = [UIImage imageWithData:data];
// 4.回到主线程,展示图片
dispatch_async(dispatch_get_main_queue(), ^{
_image.image = image;
});
});
设置总控件frame的方法
- (void) settingSubviewFrame {
// 1.封面
_image.frame = _queryFrame.imageF;

      // 2.书名
      _title.frame = _queryFrame.titleF;

      // 3.作者
      _author.frame = _queryFrame.authorF;

      // 4.出版社
      _publish.frame = _queryFrame.publishF;

      // 5.索书号
      _number.frame = _queryFrame.numberF;

      // 6.馆藏地
      _place.frame = _queryFrame.placeF;

      // 简介
      _desc.frame = _queryFrame.descF;
  }

QueryViewController中显示的内容

实现UITableViewDelegate方法,计算行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [_queryFrames[indexPath.row] cellHeight];
}
如此,遵从了MVC模式,减轻了controller的工作量,交给它的模型去做。并可以根据cell内容计算其高度

不需要计算cell高度时通过代码自定义cell

以上是需要计算cell的高度时才需要新建QueryFrame类。而当cell中控件的位置和尺寸固定时,采用代码方式创建cell时将省去计算cell的高度,要比上边的过程简单一些,这里大概罗列一下步骤:

解释为什么计算cell高度时才需要新建QueryFrame类?

数据源方法与代理方法的调用顺序:
先调用:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
再调用:且总共有多少行cell一次性全部算出
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
最后调用:
- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath )indexPath;
QueryCell是到
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; **方法中才调用的,所以,如果在QueryCell的set方法中计算frame是无效的。装有模型数据的数组中的Query并没有cell高度的数据。故需要新建QueryFrame类,拥有cellHeight属性,将其添加到拥有数据模型的数组中。

后记

小白出手,请多指教。
如言有误,还望斧正!

上一篇 下一篇

猜你喜欢

热点阅读