iOS开发——UI进阶篇(二)自定义等高cell,xib自定义等高的cell,Autolayout布局子控件,团购案例...

一、纯代码自定义等高cell


 

首先创建一个继承UITableViewCell的类
@interface XMGTgCell : UITableViewCell
在该类中依次做一下操作
1.添加子控件

 1 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
 2 {
 3 if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
 4 // 图片
 5 UIImageView *iconImageView = [[UIImageView alloc] init];
 6 [self.contentView addSubview:iconImageView];
 7 self.iconImageView = iconImageView;
 8 
 9 // 标题
10 UILabel *titleLabel = [[UILabel alloc] init];
11 [self.contentView addSubview:titleLabel];
12 self.titleLabel = titleLabel;
13 
14 // 价格
15 UILabel *priceLabel = [[UILabel alloc] init];
16 [self.contentView addSubview:priceLabel];
17 self.priceLabel = priceLabel;
18 
19 // 购买数
20 UILabel *buyCountLabel = [[UILabel alloc] init];
21 [self.contentView addSubview:buyCountLabel];
22 self.buyCountLabel = buyCountLabel;
23 }
24 return self;
25 }
创建子控件

 

2.布局子控件

/**

* 需要注意的是通过initWithStyle:创建cell,就不会调用下面这个方法
* - (instancetype)initWithFrame:(CGRect)frame;
* 那么可以layoutSubviews中计算所有子控件的frame

* 需求:图片与lable之间,lable与屏幕的margin都是10(加配图)
*/

 1 - (void)layoutSubviews
 2 {
 3 [super layoutSubviews];
 4 
 5 CGFloat margin = 10;
 6 CGFloat contentH = self.contentView.frame.size.height;
 7 CGFloat contentW = self.contentView.frame.size.width;
 8 
 9 // 图片
10 CGFloat iconX = margin;
11 CGFloat iconY = margin;
12 CGFloat iconW = 80;
13 CGFloat iconH = contentH - 2 * iconY;
14 self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);
15 
16 // 标题
17 CGFloat titleX = iconX + iconW + margin;
18 CGFloat titleY = iconY;
19 CGFloat titleW = contentW - titleX - margin;
20 CGFloat titleH = 20;
21 self.titleLabel.frame = CGRectMake(titleX, titleY, titleW, titleH);
22 
23 // 价格
24 CGFloat priceX = titleX;
25 CGFloat priceH = 15;
26 CGFloat priceY = iconY + iconH - priceH;
27 CGFloat priceW = 100;
28 self.priceLabel.frame = CGRectMake(priceX, priceY, priceW, priceH);
29 
30 // 购买数
31 CGFloat buyCountW = 150;
32 CGFloat buyCountH = 13;
33 CGFloat buyCountX = contentW - margin - buyCountW;
34 CGFloat buyCountY = iconY + iconH - buyCountH;
35 self.buyCountLabel.frame = CGRectMake(buyCountX, buyCountY, buyCountW, buyCountH);
36 }
布局子控件

 

3.设置子控件数据
在设置数据之前,我们可以创建一个TG类,用于保存每一个cell的数据,这就是典型的数据转模型,在前面也有介绍过,比如我们的数据是这样的

实现代码:

 1 /******************* XMGTg.h *******************/
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface XMGTg : NSObject
 5 /** 标题 */
 6 @property (nonatomic, copy) NSString *title;
 7 /** 购买数 */
 8 @property (nonatomic, copy) NSString *buyCount;
 9 /** 图片 */
10 @property (nonatomic, copy) NSString *icon;
11 /** 价格 */
12 @property (nonatomic, copy) NSString *price;
13 
14 + (instancetype)tgWithDict:(NSDictionary *)dict;
15 @end
16 
17 /******************* XMGTg.m *******************/
18 #import "XMGTg.h"
19 
20 @implementation XMGTg
21 + (instancetype)tgWithDict:(NSDictionary *)dict
22 {
23 XMGTg *tg = [[self alloc] init];
24 [tg setValuesForKeysWithDictionary:dict];
25 return tg;
26 }
27 @end
28 
29 /******************* XMGTgCell *******************/
30 #import <UIKit/UIKit.h>
31 @class XMGTg;
32 
33 @interface XMGTgCell : UITableViewCell
34 /** 团购模型数据 */
35 @property (nonatomic, strong) XMGTg *tg;
36 @end
37 
38 // 那么重写tg的setter方法就可以设置数据了
39 - (void)setTg:(XMGTg *)tg
40 {
41 _tg = tg;
42 
43 self.iconImageView.image = [UIImage imageNamed:tg.icon];
44 self.titleLabel.text = tg.title;
45 self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
46 self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
47 }
设置子控件数据

 

二、Autolayout布局子控件(Masonry)


 

在布局控件时我们可以使用三方框架,Masonry
那么我么可以直接把创建子控件以及布局控件全部写在
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
这个方法中

 1 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
 2 {
 3 if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
 4 CGFloat margin = 10;
 5 
 6 // 图片
 7 UIImageView *iconImageView = [[UIImageView alloc] init];
 8 [self.contentView addSubview:iconImageView];
 9 self.iconImageView = iconImageView;
10 
11 [iconImageView makeConstraints:^(MASConstraintMaker *make) {
12 make.left.top.equalTo(self.contentView).offset(margin);
13 make.bottom.equalTo(self.contentView).offset(-margin);
14 make.width.equalTo(80);
15 }];
16 
17 // 标题
18 UILabel *titleLabel = [[UILabel alloc] init];
19 [self.contentView addSubview:titleLabel];
20 self.titleLabel = titleLabel;
21 
22 [titleLabel makeConstraints:^(MASConstraintMaker *make) {
23 make.top.equalTo(iconImageView);
24 make.left.equalTo(iconImageView.right).offset(margin);
25 make.height.equalTo(20);
26 make.right.equalTo(self.contentView).offset(-margin);
27 }];
28 
29 // 价格
30 UILabel *priceLabel = [[UILabel alloc] init];
31 priceLabel.font = [UIFont systemFontOfSize:15];
32 priceLabel.textColor = [UIColor orangeColor];
33 [self.contentView addSubview:priceLabel];
34 self.priceLabel = priceLabel;
35 
36 [priceLabel makeConstraints:^(MASConstraintMaker *make) {
37 make.left.equalTo(titleLabel);
38 make.bottom.equalTo(iconImageView);
39 make.size.equalTo(CGSizeMake(100, 15));
40 }];
41 
42 // 购买数
43 UILabel *buyCountLabel = [[UILabel alloc] init];
44 buyCountLabel.font = [UIFont systemFontOfSize:13];
45 buyCountLabel.textColor = [UIColor grayColor];
46 buyCountLabel.textAlignment = NSTextAlignmentRight;
47 [self.contentView addSubview:buyCountLabel];
48 self.buyCountLabel = buyCountLabel;
49 
50 [buyCountLabel makeConstraints:^(MASConstraintMaker *make) {
51 make.bottom.equalTo(iconImageView);
52 make.right.equalTo(titleLabel);
53 make.size.equalTo(CGSizeMake(150, 13));
54 }];
55 }
56 return self;
57 }
使用三方框架布局子控件

 

三、字典转模型的几种方式(MJExtension)


 

1.遍历数组
一般最笨的方法分以下三步:加载字典数组、创建模型数组、将字典数组转换为模型数组
示例代码如下:

 1 - (NSArray *)tgs
 2 {
 3 if (!_tgs) {
 4 // 加载字典数组
 5 NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]];
 6 
 7 // 创建模型数组
 8 NSMutableArray *tgArray = [NSMutableArray array];
 9 
10 // 将字典数组 -> 模型数组
11 for (NSDictionary *dict in dictArray) {
12 XMGTg *tg = [XMGTg tgWithDict:dict];
13 [tgArray addObject:tg];
14 } 
15 _tgs = tgArray;
16 }
17 return _tgs;
18 }

 

2.世界流行框架MJExtension
再来看看用李明杰的MJExtension框架怎么解决
有一个方法,一句话可以解决

_tgs = [XMGTg objectArrayWithFilename:@"tgs.plist"];

或者这样

_tgs = [XMGTg objectArrayWithFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]];

或是这样

_tgs = [XMGTg objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]]];

那么在上次说到的索引条案例中可以这样写

// 懒加载
- (NSArray *)cargroups
{
if (!_cargroups) { 
// 提前告诉CarGroup类其中的Cars数组要解析成什么模型数组
[CarGroup setupObjectClassInArray:^NSDictionary *{
return @{
@"cars": @"Car"
};
}];
_cargroups = [CarGroup objectArrayWithFilename:@"cars.plist"];

}
return _cargroups;
}

 

四、xib自定义等高的cell


 

首先可以先创建一个名为XMGTgCell继承UITableViewCell的类
然后创建你想要的xib文件


并且xib中的Custom Class中的class一定要设置成XMGTgCell
最后在XMGTgCell的实现中重写

- (void)setTg:(XMGTg *)tg
设置数据

 1 #import <UIKit/UIKit.h>
 2 
 3 @class XMGTg;
 4 
 5 @interface XMGTgCell : UITableViewCell
 6 /** 团购模型数据 */
 7 @property (nonatomic, strong) XMGTg *tg;
 8 @end
 9 
10 #import "XMGTgCell.h"
11 #import "XMGTg.h"
12 
13 @interface XMGTgCell()
14 @property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
15 @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
16 @property (weak, nonatomic) IBOutlet UILabel *priceLabel;
17 @property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;
18 @end
19 
20 @implementation XMGTgCell
21 
22 - (void)setTg:(XMGTg *)tg
23 {
24 _tg = tg;
25 
26 self.iconImageView.image = [UIImage imageNamed:tg.icon];
27 self.titleLabel.text = tg.title;
28 self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
29 self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
30 }
31 @end

 

五、不同类型的cell共存


 

首先在cellForRowAtIndexPath方法中返回不同类型的cell

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3 if (indexPath.row % 2 == 0) {
 4 XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:tgID];
 5 cell.tg = self.tgs[indexPath.row];
 6 return cell;
 7 } else {
 8 XMGNewsCell *cell = [tableView dequeueReusableCellWithIdentifier:newsID];
 9 return cell;
10 } 
11 }

并且在使用这些cell之前要先注册

- (void)viewDidLoad {
[super viewDidLoad];

self.tableView.rowHeight = 70;

[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGTgCell class]) bundle:nil] forCellReuseIdentifier:tgID];
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGNewsCell class]) bundle:nil] forCellReuseIdentifier:newsID];
}

 

效果如下

六、storyboard自定义cell


这两种不同的cell绑定的Identifier分别为:tg、test
那么让我们来看下代码

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3 if (indexPath.row % 2 == 0) {
 4 static NSString *ID = @"tg";
 5 XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
 6 
 7 cell.tg = self.tgs[indexPath.row];
 8 
 9 return cell;
10 } else {
11 return [tableView dequeueReusableCellWithIdentifier:@"test"];
12 }
13 }

如果我们在viewDidLoad注册一个Identifier为tg,并且类型为UITableViewCell的cell,会出现什么情况呢

- (void)viewDidLoad {
[super viewDidLoad];

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"tg"];
}

经过测试,发现运行程序会直接蹦了,并且报了一个错误
reason: '-[UITableViewCell setTg:]: unrecognized selector sent to instance 0x7f8fcbc2be70'

这里是什么意思呢,首先在这里要知道 "当缓存池中找不到cell 的时候,先根据重用标识从注册这里找,然后再从storysboard中找"
这个错误的意思是发送了一个不能识别的消息-[UITableViewCell setTg:]
也就是说UITableViewCell中的setTg方法它找不到,程序运行到
"cell.tg = self.tgs[indexPath.row];这一句时就会报错,因为我们根本没有在UITableViewCell里创建tg这个属性,自然也就找不到tg的set方法,进而可以验证上面所说的系统会优先选择代码创建的cell而不是storyboard里的"

 

七、分割线,静态cell


 

分割线的原理:实际上cell中的Content View的高度要比cell少1左右的高度(大概),那么我们可以紧贴着Content View底部添加一个高度为0~1、宽度等于cell的view,并把颜色设置为灰色,最好将self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;不显示分割线

静态cell,iPhone的设置界面就是用的静态cell

八、团购案例(TG)

最后是今天自己敲的完整的代码

团购案例
  1 #import <UIKit/UIKit.h>
  2 
  3 @interface ViewController : UITableViewController
  4 
  5 @end
  6 
  7 #import "ViewController.h"
  8 #import "TgCellTableViewCell.h"
  9 #import "MJExtension.h"
 10 #import "TgCell.h"
 11 
 12 #define ID  @"chgCell"
 13 
 14 @interface ViewController ()
 15 @property (nonatomic, strong) NSArray *tgCells;
 16 @end
 17 
 18 @implementation ViewController
 19 - (NSArray *)tgCells
 20 {
 21     if (nil == _tgCells) {
 22         _tgCells = [TgCell objectArrayWithFilename:@"tgs.plist"];
 23     }
 24     return _tgCells;
 25 }
 26 
 27 - (void)viewDidLoad {
 28     [super viewDidLoad];
 29     self.tableView.rowHeight = 70;
 30     
 31 //    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 32     
 33     [self.tableView registerClass:[TgCellTableViewCell class] forCellReuseIdentifier:ID];
 34     
 35 }
 36 
 37 - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 38 {
 39     return self.tgCells.count;
 40 }
 41 
 42 - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
 43 {
 44     TgCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
 45     cell.tgcell = self.tgCells[indexPath.row];
 46     
 47     return cell;
 48 }
 49 @end
 50 
 51 /**************** TgCellTableViewCell*******************/
 52 #import <UIKit/UIKit.h>
 53 #import "TgCell.h"
 54 @interface TgCellTableViewCell : UITableViewCell
 55 @property (nonatomic, strong) TgCell *tgcell;
 56 @end
 57 
 58 #import "TgCellTableViewCell.h"
 59 
 60 @interface TgCellTableViewCell()
 61 // 图标
 62 @property (nonatomic, weak) UIImageView *icon_imageView;
 63 // 标题
 64 @property (nonatomic, weak) UILabel *titel_lable;
 65 // 价格
 66 @property (nonatomic, weak) UILabel *price_lable;
 67 // 购买人数
 68 @property (nonatomic, weak) UILabel *buy_lable;
 69 
 70 @end
 71 
 72 @implementation TgCellTableViewCell
 73 
 74 // 添加一个灰色的边框
 75 - (void)awakeFromNib
 76 {
 77     self.layer.borderWidth = 1;
 78     self.layer.borderColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.3].CGColor;
 79 }
 80 
 81 // 添加所有子控件
 82 - (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
 83 {
 84     if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
 85         // 1.创建图标
 86         UIImageView *icon_imageView = [[UIImageView alloc] init];
 87         [self.contentView addSubview:icon_imageView];
 88         self.icon_imageView = icon_imageView;
 89         
 90         // 2.创建标题
 91         UILabel *titel_lable = [[UILabel alloc] init];
 92         [self.contentView addSubview:titel_lable];
 93         self.titel_lable = titel_lable;
 94         
 95         // 3.创建价格
 96         UILabel *price_lable = [[UILabel alloc] init];
 97         [self.contentView addSubview:price_lable];
 98         price_lable.textColor = [UIColor orangeColor];
 99         price_lable.font = [UIFont systemFontOfSize:15];
100         self.price_lable = price_lable;
101         
102         
103         // 4.创建购买人数
104         UILabel *buy_lable = [[UILabel alloc] init];
105         [self.contentView addSubview:buy_lable];
106         buy_lable.textAlignment = NSTextAlignmentRight;
107         buy_lable.textColor = [UIColor grayColor];
108         buy_lable.font = [UIFont systemFontOfSize:13];
109         self.buy_lable = buy_lable;
110         
111     }
112     return self;
113 }
114 
115 
116 
117 // 布局控件
118 - (void)layoutSubviews
119 {
120     [super layoutSubviews];
121     
122     CGFloat margin = 10;
123     CGFloat contentW = self.contentView.frame.size.width;
124     CGFloat contentH = self.contentView.frame.size.height;
125     // 设置frame
126     // 1、设置图标的frame
127     CGFloat icon_imageViewX = margin;
128     CGFloat icon_imageViewY = margin;
129     CGFloat icon_imageViewW = 80;
130     CGFloat icon_imageViewH = contentH - 2 * margin;
131     self.icon_imageView.frame = CGRectMake(icon_imageViewX, icon_imageViewY, icon_imageViewW, icon_imageViewH);
132     
133     // 2、设置标题的frame
134     CGFloat titel_lableX = CGRectGetMaxX(self.icon_imageView.frame) + margin;
135     CGFloat titel_lableY = margin;
136     CGFloat titel_lableW = contentW - titel_lableX - margin;
137     CGFloat titel_lableH = 20;
138     self.titel_lable.frame = CGRectMake(titel_lableX, titel_lableY, titel_lableW, titel_lableH);
139     
140     // 3、设置价格的frame
141     CGFloat price_lableX = titel_lableX;
142     CGFloat price_lableH = 15;
143     CGFloat price_lableW = 100;
144     CGFloat price_lableY = CGRectGetMaxY(self.icon_imageView.frame) - price_lableH;
145     self.price_lable.frame = CGRectMake(price_lableX, price_lableY, price_lableW, price_lableH);
146     
147     // 4、设置购买人数的frame
148     CGFloat buy_lableX = CGRectGetMaxX(self.price_lable.frame) + margin;
149     CGFloat buy_lableH = 13;
150     CGFloat buy_lableY = CGRectGetMaxY(self.icon_imageView.frame) - buy_lableH;
151     CGFloat buy_lableW = contentW - buy_lableX - margin;
152     self.buy_lable.frame = CGRectMake(buy_lableX, buy_lableY, buy_lableW, buy_lableH);
153     
154 }
155 
156 - (void)setTgcell:(TgCell *)tgcell
157 {
158     _tgcell = tgcell;
159     
160     self.icon_imageView.image = [UIImage imageNamed:tgcell.icon];
161     self.titel_lable.text = tgcell.title;
162     self.price_lable.text = [NSString stringWithFormat:@"¥%@",tgcell.price];
163     self.buy_lable.text = [NSString stringWithFormat:@"%@人购买",tgcell.buyCount];
164 }
165 
166 @end
167 
168 /**************** TgCell*******************/
169 #import <Foundation/Foundation.h>
170 
171 @interface TgCell : NSObject
172 /** 标题 */
173 @property (nonatomic, copy) NSString *title;
174 /** 购买数 */
175 @property (nonatomic, copy) NSString *buyCount;
176 /** 图片 */
177 @property (nonatomic, copy) NSString *icon;
178 /** 价格 */
179 @property (nonatomic, copy) NSString *price;
180 @end
181 
182 #import "TgCell.h"
183 
184 @implementation TgCell
185 
186 @end

 

转载于:https://www.cnblogs.com/chglog/p/4663136.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值