一、实现效果

二、使用纯代码自定义一个tableview的步骤

1.新建一个继承自UITableViewCell的类

2.重写initWithStyle:reuseIdentifier:方法

添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中)

进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)

3.提供2个模型

数据模型: 存放文字数据\图片数据

frame模型: 存放数据模型\所有子控件的frame\cell的高度

4.cell拥有一个frame模型(不要直接拥有数据模型)

5.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame

6.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)

三、文件结构和实现代码

1.文件结构

2.实现代码:

NJWeibo.h文件

 1 #import <Foundation/Foundation.h>
 2
 3 @interface NJWeibo : NSObject
 4 @property (nonatomic, copy) NSString *text; // 内容
 5 @property (nonatomic, copy) NSString *icon; // 头像
 6 @property (nonatomic, copy) NSString *name; // 昵称
 7 @property (nonatomic, copy) NSString *picture; // 配图
 8 @property (nonatomic, assign) BOOL vip;
 9
10 - (id)initWithDict:(NSDictionary *)dict;
11 + (id)weiboWithDict:(NSDictionary *)dict;
12 @end

NJWeibo.m文件

 1 #import "NJWeibo.h"
 2
 3 @implementation NJWeibo
 4
 5 - (id)initWithDict:(NSDictionary *)dict
 6 {
 7     if (self = [super init]) {
 8         [self setValuesForKeysWithDictionary:dict];
 9     }
10     return self;
11 }
12
13 + (id)weiboWithDict:(NSDictionary *)dict
14 {
15     return [[self alloc] initWithDict:dict];
16 }
17
18 @end

NJWeiboCell.h文件

 1 #import <UIKit/UIKit.h>
 2 @class NJWeiboFrame;
 3
 4 @interface NJWeiboCell : UITableViewCell
 5 /**
 6  *  接收外界传入的模型
 7  */
 8 //@property (nonatomic, strong) NJWeibo *weibo;
 9
10 @property (nonatomic, strong) NJWeiboFrame *weiboFrame;
11
12 + (instancetype)cellWithTableView:(UITableView *)tableView;
13 @end

NJWeiboCell.m文件

  1 #import "NJWeiboCell.h"
  2 #import "NJWeibo.h"
  3 #import "NJWeiboFrame.h"
  4
  5 #define NJNameFont [UIFont systemFontOfSize:15]
  6 #define NJTextFont [UIFont systemFontOfSize:16]
  7
  8 @interface NJWeiboCell ()
  9 /**
 10  *  头像
 11  */
 12 @property (nonatomic, weak) UIImageView *iconView;
 13 /**
 14  *  vip
 15  */
 16 @property (nonatomic, weak) UIImageView *vipView;
 17 /**
 18  *  配图
 19  */
 20 @property (nonatomic, weak) UIImageView *pictureView;
 21 /**
 22  *  昵称
 23  */
 24 @property (nonatomic, weak) UILabel *nameLabel;
 25 /**
 26  *  正文
 27  */
 28 @property (nonatomic, weak) UILabel *introLabel;
 29 @end
 30
 31 @implementation NJWeiboCell
 32
 33 + (instancetype)cellWithTableView:(UITableView *)tableView
 34 {
 35     // NSLog(@"cellForRowAtIndexPath");
 36     static NSString *identifier = @"status";
 37     // 1.缓存中取
 38     NJWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
 39     // 2.创建
 40     if (cell == nil) {
 41         cell = [[NJWeiboCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
 42     }
 43     return cell;
 44 }
 45
 46
 47 /**
 48  *  构造方法(在初始化对象的时候会调用)
 49  *  一般在这个方法中添加需要显示的子控件
 50  */
 51 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
 52 {
 53     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
 54     if (self) {
 55         // 让自定义Cell和系统的cell一样, 一创建出来就拥有一些子控件提供给我们使用
 56         // 1.创建头像
 57         UIImageView *iconView = [[UIImageView alloc] init];
 58         [self.contentView addSubview:iconView];
 59         self.iconView = iconView;
 60
 61         // 2.创建昵称
 62         UILabel *nameLabel = [[UILabel alloc] init];
 63         nameLabel.font = NJNameFont;
 64         // nameLabel.backgroundColor = [UIColor redColor];
 65         [self.contentView addSubview:nameLabel];
 66         self.nameLabel = nameLabel;
 67
 68         // 3.创建vip
 69         UIImageView *vipView = [[UIImageView alloc] init];
 70         vipView.image = [UIImage imageNamed:@"vip"];
 71         [self.contentView addSubview:vipView];
 72         self.vipView = vipView;
 73
 74         // 4.创建正文
 75         UILabel *introLabel = [[UILabel alloc] init];
 76         introLabel.font = NJTextFont;
 77         introLabel.numberOfLines = 0;
 78         // introLabel.backgroundColor = [UIColor greenColor];
 79         [self.contentView addSubview:introLabel];
 80         self.introLabel = introLabel;
 81
 82         // 5.创建配图
 83         UIImageView *pictureView = [[UIImageView alloc] init];
 84         [self.contentView addSubview:pictureView];
 85         self.pictureView = pictureView;
 86
 87     }
 88     return self;
 89 }
 90
 91
 92 - (void)setWeiboFrame:(NJWeiboFrame *)weiboFrame
 93 {
 94     _weiboFrame = weiboFrame;
 95
 96     // 1.给子控件赋值数据
 97     [self settingData];
 98     // 2.设置frame
 99     [self settingFrame];
100 }
101
102
103 /**
104  *  设置子控件的数据
105  */
106 - (void)settingData
107 {
108     NJWeibo *weibo = self.weiboFrame.weibo;
109
110     // 设置头像
111     self.iconView.image = [UIImage imageNamed:weibo.icon];
112     // 设置昵称
113     self.nameLabel.text = weibo.name;
114     // 设置vip
115     if (weibo.vip) {
116         self.vipView.hidden = NO;
117         self.nameLabel.textColor = [UIColor redColor];
118     }else
119     {
120         self.vipView.hidden = YES;
121         self.nameLabel.textColor = [UIColor blackColor];
122     }
123     // 设置内容
124     self.introLabel.text = weibo.text;
125
126     // 设置配图
127     if (weibo.picture) {// 有配图
128         self.pictureView.image = [UIImage imageNamed:weibo.picture];
129         self.pictureView.hidden = NO;
130     }else
131     {
132         self.pictureView.hidden = YES;
133     }
134 }
135 /**
136  *  设置子控件的frame
137  */
138 - (void)settingFrame
139 {
140
141        // 设置头像的frame
142     self.iconView.frame = self.weiboFrame.iconF;
143
144     // 设置昵称的frame
145         self.nameLabel.frame = self.weiboFrame.nameF;
146
147     // 设置vip的frame
148        self.vipView.frame = self.weiboFrame.vipF;
149
150     // 设置正文的frame
151        self.introLabel.frame = self.weiboFrame.introF;
152
153     // 设置配图的frame
154
155     if (self.weiboFrame.weibo.picture) {// 有配图
156         self.pictureView.frame = self.weiboFrame.pictrueF;
157     }
158 }
159
160 /**
161  *  计算文本的宽高
162  *
163  *  @param str     需要计算的文本
164  *  @param font    文本显示的字体
165  *  @param maxSize 文本显示的范围
166  *
167  *  @return 文本占用的真实宽高
168  */
169 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
170 {
171     NSDictionary *dict = @{NSFontAttributeName : font};
172     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
173     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
174     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
175     return size;
176 }
177
178 @end

NJWeiboFrame.h文件

 1 //  专门用来保存每一行数据的frame, 计算frame
 2
 3 #import <Foundation/Foundation.h>
 4 @class NJWeibo;
 5 @interface NJWeiboFrame : NSObject
 6 /**
 7  *  头像的frame
 8  */
 9 @property (nonatomic, assign) CGRect iconF;
10 /**
11  *  昵称的frame
12  */
13 @property (nonatomic, assign) CGRect nameF;
14 /**
15  *  vip的frame
16  */
17 @property (nonatomic, assign) CGRect vipF;
18 /**
19  *  正文的frame
20  */
21 @property (nonatomic, assign) CGRect introF;
22 /**
23  *  配图的frame
24  */
25 @property (nonatomic, assign) CGRect pictrueF;
26 /**
27  *  行高
28  */
29 @property (nonatomic, assign) CGFloat cellHeight;
30
31 /**
32  *  模型数据
33  */
34 @property (nonatomic, strong) NJWeibo *weibo;
35 @end

NJWeiboFrame.m文件

 1 #import "NJWeiboFrame.h"
 2 #import "NJWeibo.h"
 3 #define NJNameFont [UIFont systemFontOfSize:15]
 4 #define NJTextFont [UIFont systemFontOfSize:16]
 5
 6
 7 @implementation NJWeiboFrame
 8
 9
10 - (void)setWeibo:(NJWeibo *)weibo
11 {
12     _weibo = weibo;
13
14     // 间隙
15     CGFloat padding = 10;
16
17     // 设置头像的frame
18     CGFloat iconViewX = padding;
19     CGFloat iconViewY = padding;
20     CGFloat iconViewW = 30;
21     CGFloat iconViewH = 30;
22     self.iconF = CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH);
23
24     // 设置昵称的frame
25     // 昵称的x = 头像最大的x + 间隙
26     CGFloat nameLabelX = CGRectGetMaxX(self.iconF) + padding;
27     // 计算文字的宽高
28     CGSize nameSize = [self sizeWithString:_weibo.name font:NJNameFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
29
30     CGFloat nameLabelH = nameSize.height;
31     CGFloat nameLabelW = nameSize.width;
32     CGFloat nameLabelY = iconViewY + (iconViewH - nameLabelH) * 0.5;
33    self.nameF = CGRectMake(nameLabelX, nameLabelY, nameLabelW, nameLabelH);
34
35     // 设置vip的frame
36     CGFloat vipViewX = CGRectGetMaxX(self.nameF) + padding;
37     CGFloat vipViewY = nameLabelY;
38     CGFloat vipViewW = 14;
39     CGFloat vipViewH = 14;
40     self.vipF = CGRectMake(vipViewX, vipViewY, vipViewW, vipViewH);
41
42     // 设置正文的frame
43     CGFloat introLabelX = iconViewX;
44     CGFloat introLabelY = CGRectGetMaxY(self.iconF) + padding;
45     CGSize textSize =  [self sizeWithString:_weibo.text font:NJTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
46
47     CGFloat introLabelW = textSize.width;
48     CGFloat introLabelH = textSize.height;
49
50     self.introF = CGRectMake(introLabelX, introLabelY, introLabelW, introLabelH);
51
52     // 设置配图的frame
53     CGFloat cellHeight = 0;
54     if (_weibo.picture) {// 有配图
55         CGFloat pictureViewX = iconViewX;
56         CGFloat pictureViewY = CGRectGetMaxY(self.introF) + padding;
57         CGFloat pictureViewW = 100;
58         CGFloat pictureViewH = 100;
59         self.pictrueF = CGRectMake(pictureViewX, pictureViewY, pictureViewW, pictureViewH);
60
61         // 计算行高
62         self.cellHeight = CGRectGetMaxY(self.pictrueF) + padding;
63     }else
64     {
65         // 没有配图情况下的行高
66         self.cellHeight = CGRectGetMaxY(self.introF) + padding;
67     }
68
69 }
70
71 /**
72  *  计算文本的宽高
73  *
74  *  @param str     需要计算的文本
75  *  @param font    文本显示的字体
76  *  @param maxSize 文本显示的范围
77  *
78  *  @return 文本占用的真实宽高
79  */
80 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
81 {
82     NSDictionary *dict = @{NSFontAttributeName : font};
83     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
84     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
85     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
86     return size;
87 }
88 @end

主控制器

NJViewController.m文件

 1 #import "NJViewController.h"
 2 #import "NJWeibo.h"
 3 #import "NJWeiboCell.h"
 4 #import "NJWeiboFrame.h"
 5
 6 @interface NJViewController ()
 7 @property (nonatomic, strong) NSArray *statusFrames;
 8 @end
 9
10 @implementation NJViewController
11
12 #pragma mark - 数据源方法
13
14 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
15 {
16     return self.statusFrames.count;
17 }
18
19
20 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
21 {
22     NJWeiboCell *cell = [NJWeiboCell cellWithTableView:tableView];
23     // 3.设置数据
24    cell.weiboFrame = self.statusFrames[indexPath.row];
25
26     // 4.返回
27     return cell;
28 }
29 #pragma mark - 懒加载
30 - (NSArray *)statusFrames
31 {
32     if (_statusFrames == nil) {
33         NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];
34         NSArray *dictArray = [NSArray arrayWithContentsOfFile:fullPath];
35         NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictArray.count];
36         for (NSDictionary *dict in dictArray) {
37             // 创建模型
38             NJWeibo *weibo = [NJWeibo weiboWithDict:dict];
39             // 根据模型数据创建frame模型
40             NJWeiboFrame *wbF = [[NJWeiboFrame alloc] init];
41             wbF.weibo = weibo;
42
43             [models addObject:wbF];
44         }
45         self.statusFrames = [models copy];
46     }
47     return _statusFrames;
48 }
49
50 #pragma mark - 代理方法
51 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
52 {
53     // NSLog(@"heightForRowAtIndexPath");
54     // 取出对应航的frame模型
55     NJWeiboFrame *wbF = self.statusFrames[indexPath.row];
56     NSLog(@"height = %f", wbF.cellHeight);
57     return wbF.cellHeight;
58 }
59
60 - (BOOL) prefersStatusBarHidden
61 {
62     return YES;
63 }
64 @end

四、补充说明

由于系统提供的tableview可能并不能满足我们的开发需求,所以经常要求我们能够自定义tableview。

自定义tableview有两种方式,一种是使用xib创建,一种是使用纯代码的方式创建。

对于样式一样的tableview,通常使用xib进行创建,对于高度不一样,内容也不完全一致的通常使用纯代码进行自定义。

UI基础第十四弹:UItableview使用代码自定义团购页面相关推荐

  1. go设置后端启动_Go语言基础(十四)

    Go语言基础(十四) 一.Redis 二.NSQ 三.Go module 四.Context......0 一.Redis Redis是一个key-value存储系统.和Memcached类似,它支持 ...

  2. Java SE基础(十四)常用API

    Java SE基础(十四)常用API 概述 Object类 构造方法 成员方法 toString()方法 equals(Object obj)方法 Arrays排序 Arrays类概述 Arrays成 ...

  3. iOS 11开发教程(十四)iOS11应用代码添加视图

    iOS 11开发教程(十四)iOS11应用代码添加视图 如果开发者想要使用代码为主视图添加视图,该怎么办呢.以下将为开发者解决这一问题.要使用代码为主视图添加视图需要实现3个步骤. (1)实例化视图对 ...

  4. Java入门基础(十四)Maven仓库的安装

    文章目录 一.下载配置Maven环境 1.下载maven.jar解压缩,放在一个文件夹下 2.点击此电脑=>属性=>高级设置=>环境变量=>系统变量=>新建 3.变量名为 ...

  5. 想要专升本你不得不看的全干货_吐血整理_专升本_计算机文化基础( 十 四 )

    大家好,我是阿Ken.很快就要整理完第三章了~ 对于专升本_计算机文化基础我已经在博客里整理了已经一半多了,希望能够在我整理后能够帮助其他的小伙伴,会一直整理完所有的专升本_计算机文化基础的笔记,感兴 ...

  6. Android UI开发第二十五篇——分享一篇自定义的 Action Bar

    Action Bar是android3.0以后才引入的,主要是替代3.0以前的menu和tittle bar.在3.0之前是不能使用Action Bar功能的.这里引入了自定义的Action Bar, ...

  7. Keras(三十四)Transformer模型代码实现

    一,加载数据 0,导入深度学习包 import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np import ...

  8. 物流基础知识(十四)

    铁路货物运输的种类 铁路货物运输分为三种: 1. 整车运输:2. 零担运输: 3. 集装箱运输. 其中还包括快运,整列行包快运,但现在开展的范围不大. 一批货物的重量.体积或形状需要以一辆以上货车运输 ...

  9. 基于ROS机器人的3D物体识别与三维重建(四)视觉SLAM基础(十四讲学习记录)

    视觉SLAM基础理论 1 引言 2 视觉里程计 2.1 特征点法VO (1)对极几何与三角量测 (2)PnP问题 (3)ICP迭代最近点法 2.2 直接法VO 3 后端优化 3.1 BA与非线性优化 ...

最新文章

  1. 【转】ASP.NET AJAX入门系列
  2. 在线教育这条取经路,有道词典何时能修成正果?
  3. Python xlrd、xlwt、xlutils修改Excel文件
  4. 保存的图数据丢失_自从用了这2个功能,再也没有担心过文档丢失
  5. 【无码专区6】球与盒子(数学线性筛)
  6. MongoDB: The Definitive Guide
  7. react 子传参父_React 子组件向父组件传值的方法
  8. Java中的变量分类_开发简单的Java应用
  9. 2016CCCC天梯--多项式A除以B
  10. python 按日期筛选数据并计算均值
  11. 证明:一个有n个结点的非空二叉树的高度至少为lgn
  12. C语言调用pow( )函数实现幂运算
  13. 2018深信服java笔试题,深信服2018秋招编程题
  14. 题目0121-机器人走迷宫
  15. 微信小程序 数据在缓存中的存储和获取
  16. 这100佳创新互联网公司值得你去
  17. python:写个简陋的按键精灵
  18. 吉林银行对接支付 绑卡
  19. TomCat 启动报:validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2.
  20. 老板怎么舍得你离开?-让我来教你如何拍马屁

热门文章

  1. 保姆级 IGV 基因组浏览器使用指南(图文详解)
  2. Zookeeper客户端网络通讯模型分析
  3. Queuing HDU2604
  4. JVM、JDK、JER介绍
  5. anytime you feel the pain,hey,dear,refrain
  6. JDK自带的Timer定时器实现每天24点修改数据
  7. 学习成绩 =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。(C语言版)
  8. 在Silverlight3中使用SSME重现Big Buck Bunny播放器
  9. Duang~Shark 闪跌 99%! Fork 了 Bunny 的代码还 Fork 了它的攻击
  10. 钱多多第二阶段冲刺07