iOS開發——UI進階篇(二)自定義等高cell,xib自定義等高的cell,Autolayout佈局子控件,團購案例

1、純代碼自定義等高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中計算全部子控件的frameide

* 需求:圖片與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的數據,這就是典型的數據轉模型,在前面也有介紹過,好比咱們的數據是這樣的測試

實現代碼:atom

 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 }
設置子控件數據

 

2、Autolayout佈局子控件(Masonry)


 

在佈局控件時咱們可使用三方框架,Masonry
那麼我麼能夠直接把建立子控件以及佈局控件所有寫在
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
這個方法中spa

 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 }
使用三方框架佈局子控件

 

3、字典轉模型的幾種方式(MJExtension)


 

1.遍歷數組
通常最笨的方法分如下三步:加載字典數組、建立模型數組、將字典數組轉換爲模型數組
示例代碼以下:3d

 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框架怎麼解決
有一個方法,一句話能夠解決code

_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;
}

 

4、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

 

5、不一樣類型的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];
}

 

效果以下

6、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裏的"

 

7、分割線,靜態cell


 

分割線的原理:實際上cell中的Content View的高度要比cell少1左右的高度(大概),那麼咱們能夠緊貼着Content View底部添加一個高度爲0~一、寬度等於cell的view,並把顏色設置爲灰色,最好將self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;不顯示分割線

靜態cell,iPhone的設置界面就是用的靜態cell

8、團購案例(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     // 一、設置圖標的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     // 二、設置標題的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     // 三、設置價格的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     // 四、設置購買人數的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
相關文章
相關標籤/搜索