iOS开发——UI进阶篇(二)自定义等高cell,xib自定义等高的cell,Autolayout布局子控件,团购案例
一、纯代码自定义等高cell
首先创建一个继承UITableViewCell的类
@interface XMGTgCell : UITableViewCell
在该类中依次做一下操作
1.添加子控件
- - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
- {
- if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
- // 图片
- UIImageView *iconImageView = [[UIImageView alloc] init];
- [self.contentView addSubview:iconImageView];
- self.iconImageView = iconImageView;
- // 标题
- UILabel *titleLabel = [[UILabel alloc] init];
- [self.contentView addSubview:titleLabel];
- self.titleLabel = titleLabel;
- // 价格
- UILabel *priceLabel = [[UILabel alloc] init];
- [self.contentView addSubview:priceLabel];
- self.priceLabel = priceLabel;
- // 购买数
- UILabel *buyCountLabel = [[UILabel alloc] init];
- [self.contentView addSubview:buyCountLabel];
- self.buyCountLabel = buyCountLabel;
- }
- return self;
- }
创建子控件
2.布局子控件
/**
* 需要注意的是通过initWithStyle:创建cell,就不会调用下面这个方法
* - (instancetype)initWithFrame:(CGRect)frame;
* 那么可以在layoutSubviews中计算所有子控件的frame
* 需求:图片与lable之间,lable与屏幕的margin都是10(加配图)
*/
- - (void)layoutSubviews
- {
- [super layoutSubviews];
- CGFloat margin = ;
- CGFloat contentH = self.contentView.frame.size.height;
- CGFloat contentW = self.contentView.frame.size.width;
- // 图片
- CGFloat iconX = margin;
- CGFloat iconY = margin;
- CGFloat iconW = ;
- CGFloat iconH = contentH - * iconY;
- self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);
- // 标题
- CGFloat titleX = iconX + iconW + margin;
- CGFloat titleY = iconY;
- CGFloat titleW = contentW - titleX - margin;
- CGFloat titleH = ;
- self.titleLabel.frame = CGRectMake(titleX, titleY, titleW, titleH);
- // 价格
- CGFloat priceX = titleX;
- CGFloat priceH = ;
- CGFloat priceY = iconY + iconH - priceH;
- CGFloat priceW = ;
- self.priceLabel.frame = CGRectMake(priceX, priceY, priceW, priceH);
- // 购买数
- CGFloat buyCountW = ;
- CGFloat buyCountH = ;
- CGFloat buyCountX = contentW - margin - buyCountW;
- CGFloat buyCountY = iconY + iconH - buyCountH;
- self.buyCountLabel.frame = CGRectMake(buyCountX, buyCountY, buyCountW, buyCountH);
- }
布局子控件
3.设置子控件数据
在设置数据之前,我们可以创建一个TG类,用于保存每一个cell的数据,这就是典型的数据转模型,在前面也有介绍过,比如我们的数据是这样的
实现代码:
- /******************* XMGTg.h *******************/
- #import <Foundation/Foundation.h>
- @interface XMGTg : NSObject
- /** 标题 */
- @property (nonatomic, copy) NSString *title;
- /** 购买数 */
- @property (nonatomic, copy) NSString *buyCount;
- /** 图片 */
- @property (nonatomic, copy) NSString *icon;
- /** 价格 */
- @property (nonatomic, copy) NSString *price;
- + (instancetype)tgWithDict:(NSDictionary *)dict;
- @end
- /******************* XMGTg.m *******************/
- #import "XMGTg.h"
- @implementation XMGTg
- + (instancetype)tgWithDict:(NSDictionary *)dict
- {
- XMGTg *tg = [[self alloc] init];
- [tg setValuesForKeysWithDictionary:dict];
- return tg;
- }
- @end
- /******************* XMGTgCell *******************/
- #import <UIKit/UIKit.h>
- @class XMGTg;
- @interface XMGTgCell : UITableViewCell
- /** 团购模型数据 */
- @property (nonatomic, strong) XMGTg *tg;
- @end
- // 那么重写tg的setter方法就可以设置数据了
- - (void)setTg:(XMGTg *)tg
- {
- _tg = tg;
- self.iconImageView.image = [UIImage imageNamed:tg.icon];
- self.titleLabel.text = tg.title;
- self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
- self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
- }
设置子控件数据
二、Autolayout布局子控件(Masonry)
在布局控件时我们可以使用三方框架,Masonry
那么我么可以直接把创建子控件以及布局控件全部写在
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
这个方法中
- - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
- {
- if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
- CGFloat margin = ;
- // 图片
- UIImageView *iconImageView = [[UIImageView alloc] init];
- [self.contentView addSubview:iconImageView];
- self.iconImageView = iconImageView;
- [iconImageView makeConstraints:^(MASConstraintMaker *make) {
- make.left.top.equalTo(self.contentView).offset(margin);
- make.bottom.equalTo(self.contentView).offset(-margin);
- make.width.equalTo();
- }];
- // 标题
- UILabel *titleLabel = [[UILabel alloc] init];
- [self.contentView addSubview:titleLabel];
- self.titleLabel = titleLabel;
- [titleLabel makeConstraints:^(MASConstraintMaker *make) {
- make.top.equalTo(iconImageView);
- make.left.equalTo(iconImageView.right).offset(margin);
- make.height.equalTo();
- make.right.equalTo(self.contentView).offset(-margin);
- }];
- // 价格
- UILabel *priceLabel = [[UILabel alloc] init];
- priceLabel.font = [UIFont systemFontOfSize:];
- priceLabel.textColor = [UIColor orangeColor];
- [self.contentView addSubview:priceLabel];
- self.priceLabel = priceLabel;
- [priceLabel makeConstraints:^(MASConstraintMaker *make) {
- make.left.equalTo(titleLabel);
- make.bottom.equalTo(iconImageView);
- make.size.equalTo(CGSizeMake(, ));
- }];
- // 购买数
- UILabel *buyCountLabel = [[UILabel alloc] init];
- buyCountLabel.font = [UIFont systemFontOfSize:];
- buyCountLabel.textColor = [UIColor grayColor];
- buyCountLabel.textAlignment = NSTextAlignmentRight;
- [self.contentView addSubview:buyCountLabel];
- self.buyCountLabel = buyCountLabel;
- [buyCountLabel makeConstraints:^(MASConstraintMaker *make) {
- make.bottom.equalTo(iconImageView);
- make.right.equalTo(titleLabel);
- make.size.equalTo(CGSizeMake(, ));
- }];
- }
- return self;
- }
使用三方框架布局子控件
三、字典转模型的几种方式(MJExtension)
1.遍历数组
一般最笨的方法分以下三步:加载字典数组、创建模型数组、将字典数组转换为模型数组
示例代码如下:
- - (NSArray *)tgs
- {
- if (!_tgs) {
- // 加载字典数组
- NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]];
- // 创建模型数组
- NSMutableArray *tgArray = [NSMutableArray array];
- // 将字典数组 -> 模型数组
- for (NSDictionary *dict in dictArray) {
- XMGTg *tg = [XMGTg tgWithDict:dict];
- [tgArray addObject:tg];
- }
- _tgs = tgArray;
- }
- return _tgs;
- }
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
设置数据
- #import <UIKit/UIKit.h>
- @class XMGTg;
- @interface XMGTgCell : UITableViewCell
- /** 团购模型数据 */
- @property (nonatomic, strong) XMGTg *tg;
- @end
- #import "XMGTgCell.h"
- #import "XMGTg.h"
- @interface XMGTgCell()
- @property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
- @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
- @property (weak, nonatomic) IBOutlet UILabel *priceLabel;
- @property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;
- @end
- @implementation XMGTgCell
- - (void)setTg:(XMGTg *)tg
- {
- _tg = tg;
- self.iconImageView.image = [UIImage imageNamed:tg.icon];
- self.titleLabel.text = tg.title;
- self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
- self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
- }
- @end
五、不同类型的cell共存
首先在cellForRowAtIndexPath方法中返回不同类型的cell
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- if (indexPath.row % == ) {
- XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:tgID];
- cell.tg = self.tgs[indexPath.row];
- return cell;
- } else {
- XMGNewsCell *cell = [tableView dequeueReusableCellWithIdentifier:newsID];
- return cell;
- }
- }
并且在使用这些cell之前要先注册
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.tableView.rowHeight = ;
- [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
那么让我们来看下代码
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- if (indexPath.row % == ) {
- static NSString *ID = @"tg";
- XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
- cell.tg = self.tgs[indexPath.row];
- return cell;
- } else {
- return [tableView dequeueReusableCellWithIdentifier:@"test"];
- }
- }
如果我们在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)
最后是今天自己敲的完整的代码
- #import <UIKit/UIKit.h>
- @interface ViewController : UITableViewController
- @end
- #import "ViewController.h"
- #import "TgCellTableViewCell.h"
- #import "MJExtension.h"
- #import "TgCell.h"
- #define ID @"chgCell"
- @interface ViewController ()
- @property (nonatomic, strong) NSArray *tgCells;
- @end
- @implementation ViewController
- - (NSArray *)tgCells
- {
- if (nil == _tgCells) {
- _tgCells = [TgCell objectArrayWithFilename:@"tgs.plist"];
- }
- return _tgCells;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.tableView.rowHeight = ;
- // self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
- [self.tableView registerClass:[TgCellTableViewCell class] forCellReuseIdentifier:ID];
- }
- - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- return self.tgCells.count;
- }
- - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
- {
- TgCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
- cell.tgcell = self.tgCells[indexPath.row];
- return cell;
- }
- @end
- /**************** TgCellTableViewCell*******************/
- #import <UIKit/UIKit.h>
- #import "TgCell.h"
- @interface TgCellTableViewCell : UITableViewCell
- @property (nonatomic, strong) TgCell *tgcell;
- @end
- #import "TgCellTableViewCell.h"
- @interface TgCellTableViewCell()
- // 图标
- @property (nonatomic, weak) UIImageView *icon_imageView;
- // 标题
- @property (nonatomic, weak) UILabel *titel_lable;
- // 价格
- @property (nonatomic, weak) UILabel *price_lable;
- // 购买人数
- @property (nonatomic, weak) UILabel *buy_lable;
- @end
- @implementation TgCellTableViewCell
- // 添加一个灰色的边框
- - (void)awakeFromNib
- {
- self.layer.borderWidth = ;
- self.layer.borderColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.3].CGColor;
- }
- // 添加所有子控件
- - (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
- {
- if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
- // 1.创建图标
- UIImageView *icon_imageView = [[UIImageView alloc] init];
- [self.contentView addSubview:icon_imageView];
- self.icon_imageView = icon_imageView;
- // 2.创建标题
- UILabel *titel_lable = [[UILabel alloc] init];
- [self.contentView addSubview:titel_lable];
- self.titel_lable = titel_lable;
- // 3.创建价格
- UILabel *price_lable = [[UILabel alloc] init];
- [self.contentView addSubview:price_lable];
- price_lable.textColor = [UIColor orangeColor];
- price_lable.font = [UIFont systemFontOfSize:];
- self.price_lable = price_lable;
- // 4.创建购买人数
- UILabel *buy_lable = [[UILabel alloc] init];
- [self.contentView addSubview:buy_lable];
- buy_lable.textAlignment = NSTextAlignmentRight;
- buy_lable.textColor = [UIColor grayColor];
- buy_lable.font = [UIFont systemFontOfSize:];
- self.buy_lable = buy_lable;
- }
- return self;
- }
- // 布局控件
- - (void)layoutSubviews
- {
- [super layoutSubviews];
- CGFloat margin = ;
- CGFloat contentW = self.contentView.frame.size.width;
- CGFloat contentH = self.contentView.frame.size.height;
- // 设置frame
- // 1、设置图标的frame
- CGFloat icon_imageViewX = margin;
- CGFloat icon_imageViewY = margin;
- CGFloat icon_imageViewW = ;
- CGFloat icon_imageViewH = contentH - * margin;
- self.icon_imageView.frame = CGRectMake(icon_imageViewX, icon_imageViewY, icon_imageViewW, icon_imageViewH);
- // 2、设置标题的frame
- CGFloat titel_lableX = CGRectGetMaxX(self.icon_imageView.frame) + margin;
- CGFloat titel_lableY = margin;
- CGFloat titel_lableW = contentW - titel_lableX - margin;
- CGFloat titel_lableH = ;
- self.titel_lable.frame = CGRectMake(titel_lableX, titel_lableY, titel_lableW, titel_lableH);
- // 3、设置价格的frame
- CGFloat price_lableX = titel_lableX;
- CGFloat price_lableH = ;
- CGFloat price_lableW = ;
- CGFloat price_lableY = CGRectGetMaxY(self.icon_imageView.frame) - price_lableH;
- self.price_lable.frame = CGRectMake(price_lableX, price_lableY, price_lableW, price_lableH);
- // 4、设置购买人数的frame
- CGFloat buy_lableX = CGRectGetMaxX(self.price_lable.frame) + margin;
- CGFloat buy_lableH = ;
- CGFloat buy_lableY = CGRectGetMaxY(self.icon_imageView.frame) - buy_lableH;
- CGFloat buy_lableW = contentW - buy_lableX - margin;
- self.buy_lable.frame = CGRectMake(buy_lableX, buy_lableY, buy_lableW, buy_lableH);
- }
- - (void)setTgcell:(TgCell *)tgcell
- {
- _tgcell = tgcell;
- self.icon_imageView.image = [UIImage imageNamed:tgcell.icon];
- self.titel_lable.text = tgcell.title;
- self.price_lable.text = [NSString stringWithFormat:@"¥%@",tgcell.price];
- self.buy_lable.text = [NSString stringWithFormat:@"%@人购买",tgcell.buyCount];
- }
- @end
- /**************** TgCell*******************/
- #import <Foundation/Foundation.h>
- @interface TgCell : NSObject
- /** 标题 */
- @property (nonatomic, copy) NSString *title;
- /** 购买数 */
- @property (nonatomic, copy) NSString *buyCount;
- /** 图片 */
- @property (nonatomic, copy) NSString *icon;
- /** 价格 */
- @property (nonatomic, copy) NSString *price;
- @end
- #import "TgCell.h"
- @implementation TgCell
- @end
iOS开发——UI进阶篇(二)自定义等高cell,xib自定义等高的cell,Autolayout布局子控件,团购案例的更多相关文章
- iOS开发——UI进阶篇(三)自定义不等高cell,如何拿到cell的行高,自动计算cell高度,(有配图,无配图)微博案例
一.纯代码自定义不等高cell 废话不多说,直接来看下面这个例子先来看下微博的最终效果 首先创建一个继承UITableViewController的控制器@interface ViewControll ...
- iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期
一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // ...
- iOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别
触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponde ...
- iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果
一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...
- iOS开发——UI进阶篇(四)tableView的全局刷新,局部刷新,左滑操作,左滑出现更多按钮,进入编辑模式,批量删除,自定义批量删除
首先创建项目,在storyboard如下布局控件,设置好约束 然后创建cell模型类XMGWineCell数据模型类XMGWine创建UITableView,设置数据源协议,实现数据源方法懒加载数据这 ...
- iOS开发——UI进阶篇(十五)Quartz2D介绍
一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...
- iOS开发——UI进阶篇(七)程序启动原理、打电话、发短信
一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 ...
- iOS开发——UI进阶篇(十七)CALayer,核心动画基本使用
一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以 ...
- iOS开发——UI进阶篇(十六)Quartz2D实战小例子
一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画 ...
随机推荐
- Cheminformatic Set
蛋白: 数据库 1. 蛋白晶体结构数据库 http://www.rcsb.org/pdb/home/home.do 2. 蛋白注释数据库 http://www.uniprot.org/ 工具 1. r ...
- SSM的各个配置文件
SqlMapConfig.xml文件:(这是带了mybatis的分页插件的配置) <?xml version="1.0" encoding="UTF-8" ...
- 【原】gulp快速入门
今天刚入职了一家新公司,结果明天就要开始项目了.上级说要用gulp来打包代码,所以今晚花了一晚来看这个gulp, 可以说已经入门了.所以做一个小小的总结 : 首先全局安装gulp npm instal ...
- JavaWeb学习笔记——DAO设计模式
- CMAKE使用
http://www.cppblog.com/tx7do/archive/2010/08/19/124000.html http://blog.csdn.net/dbzhang800/article/ ...
- VIM的姿势
http://blog.csdn.net/vincent_czz/article/details/7900670 http://bbs.feng.com/read-htm-tid-7435912.ht ...
- JSONModel 嵌套字典数组 JSONModel nest NSDictionary NSArray
JSONModel 嵌套字典数组 JSONModel nest NSDictionary NSArray
- MBProgressHUD+FastCall
+ (void)showHudTipStr:(NSString *)tipStr; + (void)showHudTipStr:(NSString *)tipStr{ ) { MBProgressHU ...
- php Hash Table(二) Hash函数
哈希表最关键的几个方面有: 通过key访问(通过哈希函数计算出key) 映射到数据结构中(哈希表本身的存储结构) 映射的处理(冲突或者碰撞检测和处理函数) 理解PHP的哈希算法 一般来说对于整形索引进 ...
- Python Web Crawler
Python版本:3.5.2 pycharm URL Parsing¶ https://docs.python.org/3.5/library/urllib.parse.html?highlight= ...