IOS开发UI篇--UITableView的自定义布局==纯代码布局
2014-05-29 20:27
363 查看
UITableView中除了利用系统的UItableViewCell不能完成需求进行布局时,还可以进行自定义布局;
自定义布局分为两类:(1)利用代码进行创建
(2)利用xib进行实现;
下面对利用代码进行创建分析:
下面以一个例子进行说明:
由于本案例整个界面就是单独的一个UITableView,故而主控制器设置成UITableViewController;这样可以减少很多连线问题,
因为UITableViewController里面已进行关联,且内部也开放出来了tableview;可以直接使用
(1)下面是一个SLViewController.m文件
(2)这个SLWeiBo.H与SLWeiBo.m Global.h文件
第一个文件是定义一些基本属性,用来进行字典转换模型;并定义了两个方法,一个是类方法,一个实例方法,在第二个文件中进行实现
第三个文件是对第一个和第二个文件的定义方法进行的抽取,方便重用,第三个文件利用定义宏进行代码抽取,
(3)SLWeiBoCell.h和SLWeiBoCell.m文件是继承自UITableViewCell的,是对UITableViewCell进行的重写,已到达所需要的要求界面,
并设置数据,与设置位置。
(4)SLWeiBoFrame.h和SLWeiBoFrame.m 文件是为了求行高而进行的数据抽取,即先计算出行的高,并且保存每行中控件的位置;
方便传给cell进行利用;
最终实现效果图如下:
以上方法,即是利用代码进行对UITableViewCell进行的重写,下一讲讲解关于
利用xib创建重用的单元格对象。
自定义布局分为两类:(1)利用代码进行创建
(2)利用xib进行实现;
下面对利用代码进行创建分析:
应用场景:像微博,等列表数据展示(由于微博的每个单元格的数据大小不一致,所以得计算每个单元格的大小) 分析:前提是获取列表数据,然后建立每个单元格的模型(建立单元格模型应继承UITableViewCell)复写 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 此方法即可,在此方法中添加单元格所需要的各个视图控件, 然后根据微博对象模型,确定每个控件的位置,并进行数据 的填充, 主要在此方法中几个重要的方法:(特别是方法的执行顺序) 1.-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 2.-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
下面以一个例子进行说明:
由于本案例整个界面就是单独的一个UITableView,故而主控制器设置成UITableViewController;这样可以减少很多连线问题,
因为UITableViewController里面已进行关联,且内部也开放出来了tableview;可以直接使用
(1)下面是一个SLViewController.m文件
#import "SLViewController.h" #import "SLWeiBo.h" #import "SLWeiBoCell.h" #import "SLWeiBoFrame.h" @interface SLViewController () //定义数组,保存模型数据 @property (nonatomic,strong)NSArray *statusFrames; @end @implementation SLViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView ; } #pragma mark -懒加载 -(NSArray *)statusFrames { if (_statusFrames==nil) { //加载plist数据文件 NSString *fullpath=[[NSBundle mainBundle] pathForResource:@"statuses" ofType:@"plist"]; NSArray *arr=[NSArray arrayWithContentsOfFile:fullpath]; NSMutableArray *mutearr=[NSMutableArray arrayWithCapacity:arr.count]; for (NSDictionary *dict in arr) { //字典转模型,传进去一个字典,返回一个微博模型 SLWeiBo *weibo=[SLWeiBo weiBoWithDict:dict]; //计算每一个表格的高度并保存 SLWeiBoFrame *weiboframe=[[SLWeiBoFrame alloc] init]; weiboframe.weibo=weibo; //把Frame模型保存到数组中 [mutearr addObject:weiboframe]; } self.statusFrames=[mutearr mutableCopy]; } return _statusFrames; } #pragma mark -实现数据源方法 /** * tableview中返回一共有多少组,有一组的话,可以省略不写 * * @param tableView * * @return 返回有多少组 */ -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { return 1; } /** * tableview返回一共有多少个单元格 * * @param tableView * @param section 第几组 * * @return 某组有多少单元格 */ -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.statusFrames.count; } /** * tableView返回每个单元格的对象 * * @param tableView * @param indexPath 保存有该对象是第几组,第几个单元格 * * @return 返回每个单元格对象 */ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //1.从缓存中取数据 static NSString *identifier=@"status"; SLWeiBoCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier]; //2创建表格 if (cell==nil) { cell=[[SLWeiBoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } //3设置数据 SLWeiBoFrame *frame=self.statusFrames[indexPath.row]; cell.itemframe=frame; return cell; } #pragma mark -实现高度的代理方法 /** * 计算每个单元格的高度 * * @param tableView * @param indexPath 该单元格是某组某行的单元格 * * @return 返回该单元格的高度 */ -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { SLWeiBoFrame *frame=self.statusFrames[indexPath.row]; return frame.cellHeight; } /** * 设置是否显示状态栏 * * @return 返回YES,不显示,返回NO,显示 */ -(BOOL)prefersStatusBarHidden { return NO; } @end
(2)这个SLWeiBo.H与SLWeiBo.m Global.h文件
第一个文件是定义一些基本属性,用来进行字典转换模型;并定义了两个方法,一个是类方法,一个实例方法,在第二个文件中进行实现
第三个文件是对第一个和第二个文件的定义方法进行的抽取,方便重用,第三个文件利用定义宏进行代码抽取,
#import "Global.h" /** * 创建一个微博对象,保存模型数据 */ @interface SLWeiBo : NSObject @property (nonatomic,copy) NSString *text;//内容 @property (nonatomic,copy) NSString *icon;//头像 @property (nonatomic,copy) NSString *name;//昵称 @property (nonatomic,copy) NSString *picture;//配图 //是否是vip @property (nonatomic,assign) BOOL vip; initWeiBo(weiBo) ////进行转换的实例方法 //-(instancetype)initWithWeiBo:(NSDictionary *)dict; //// 进行转换的类方法 //+(instancetype)weiBoWithDict:(NSDictionary *)dict; @end
#import "SLWeiBo.h" @implementation SLWeiBo //分别对类方法和实例方法进行实现 weiBoInitDict(weiBo); //-(instancetype)initWithWeiBo:(NSDictionary *)dict; //{ // if (self=[super init]) { // [self setValuesForKeysWithDictionary:dict]; // } // return self; //} // //+(instancetype)weiBoWithDict:(NSDictionary *)dict //{ // return [[self alloc] initWithWeiBo:dict]; //} @end
#ifndef ___Global_h #define ___Global_h #define initWeiBo(name)\ -(instancetype) initWithWeiBo:(NSDictionary *)dict;\ +(instancetype) name##WithDict:(NSDictionary *)dict; #define weiBoInitDict(name)\ -(instancetype) initWithWeiBo:(NSDictionary *)dict;\ {\ if (self=[super init]) {\ [self setValuesForKeysWithDictionary:dict];\ }\ return self;\ }\ +(instancetype) name##WithDict:(NSDictionary *)dict\ {\ return [[self alloc] initWithWeiBo:dict];\ } #endif
(3)SLWeiBoCell.h和SLWeiBoCell.m文件是继承自UITableViewCell的,是对UITableViewCell进行的重写,已到达所需要的要求界面,
并设置数据,与设置位置。
#import <UIKit/UIKit.h> @class SLWeiBoFrame; @interface SLWeiBoCell : UITableViewCell //导入SLweiboFrame对象,保存着一个单元格里面每个控件的位置,及weibo对象 @property (nonatomic,strong) SLWeiBoFrame *itemframe; @end
#import "SLWeiBoCell.h" #import "SLWeiBoFrame.h" #define SLFontNiCheng [UIFont systemFontOfSize:15] #define SLFontZhengWen [UIFont systemFontOfSize:16] @interface SLWeiBoCell() //头部头像 @property (nonatomic,weak) UIImageView *iconheader; //昵称 @property (nonatomic,weak) UILabel *nicheng; //是否是vip @property (nonatomic,weak) UIImageView *vip; //正文显示 @property (nonatomic,weak) UILabel *zhengwen; //配图显示 @property (nonatomic,weak) UIImageView *peitu; @end @implementation SLWeiBoCell //复写此方法,以达到重写UITableViewCell的目的 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // 让自定义cell和系统的cell一样,创建出来就拥有一些子控件提供给我们使用 //1.创建头像 UIImageView *iconheader=[[UIImageView alloc] init]; [self.contentView addSubview:iconheader]; self.iconheader=iconheader; //2.创建昵称 UILabel *nicheng=[[UILabel alloc] init]; nicheng.font=SLFontNiCheng; [self.contentView addSubview:nicheng]; self.nicheng=nicheng; //3.创建vip UIImageView *vip=[[UIImageView alloc] init]; vip.image=[UIImage imageNamed:@"vip"]; [self.contentView addSubview:vip]; self.vip=vip; //4创建正文 UILabel *zhengwen=[[UILabel alloc] init]; //让正文进行多行显示 zhengwen.numberOfLines=0; //设置正文的字体,此时的字体应该在和计算该正文的字体长宽所用字体一致, zhengwen.font=SLFontZhengWen; [self.contentView addSubview:zhengwen]; self.zhengwen=zhengwen; //5创建配图 UIImageView *peitu=[[UIImageView alloc] init]; [self.contentView addSubview:peitu]; self.peitu=peitu; } return self; } -(void)setItemframe:(SLWeiBoFrame *)itemframe { _itemframe=itemframe; //设置数据 [self settingData]; //设置frame [self settingFrame]; } -(void)settingData { //设置头像 SLWeiBo *weibof=self.itemframe.weibo; self.iconheader.image=[UIImage imageNamed:weibof.icon]; //设置昵称 self.nicheng.text=weibof.name; //设置vip if (weibof.vip) { self.nicheng.textColor=[UIColor redColor]; self.vip.hidden=NO; }else{ self.nicheng.textColor=[UIColor blackColor]; self.vip.hidden=YES; } //设置内容 self.zhengwen.text=weibof.text; //设置配图 if (weibof.picture) { self.peitu.image=[UIImage imageNamed:weibof.picture]; self.peitu.hidden=NO; }else{ self.peitu.hidden=YES; } } -(void)settingFrame { //1设置头像的frame self.iconheader.frame=self.itemframe.iconF; //2设置昵称的frame self.nicheng.frame=self.itemframe.nichengF; //3设置vip的frame self.vip.frame=self.itemframe.vipF; //4设置正文的frame self.zhengwen.frame=self.itemframe.zhengwenF; //5设置配图的frame if (self.itemframe.weibo.picture) { self.peitu.frame=self.itemframe.peituF; } } @end
(4)SLWeiBoFrame.h和SLWeiBoFrame.m 文件是为了求行高而进行的数据抽取,即先计算出行的高,并且保存每行中控件的位置;
方便传给cell进行利用;
#import "SLWeiBo.h" @interface SLWeiBoFrame : NSObject /** 头像的frame */ @property (nonatomic,assign) CGRect iconF; /** 昵称的frame */ @property (nonatomic,assign) CGRect nichengF; /** vip的frame */ @property (nonatomic,assign) CGRect vipF; /** 正文的frame */ @property (nonatomic,assign) CGRect zhengwenF; /** 配图的frame */ @property (nonatomic,assign) CGRect peituF; /** 行高 */ @property (nonatomic,assign) CGFloat cellHeight; @property (nonatomic,strong) SLWeiBo *weibo; @end
#import "SLWeiBoFrame.h" #import "SLWeiBo.h" #define SLFontNiCheng [UIFont systemFontOfSize:15] #define SLFontZhengWen [UIFont systemFontOfSize:16] @implementation SLWeiBoFrame -(void)setWeibo:(SLWeiBo *)weibo { _weibo=weibo; //间隙 CGFloat padding=10; //1设置头像的frame CGFloat iconViewX=padding; CGFloat iconViewY=padding; CGFloat iconViewW=30; CGFloat iconViewH=30; self.iconF=CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH); //2设置昵称的frame CGFloat nichengX=CGRectGetMaxX(self.iconF)+padding; /** * attributes 告诉系统文字的大小 */ // NSDictionary *dict=@{NSFontAttributeName:[UIFont systemFontOfSize:15]}; // 如果将来计算的文字的范围超出了指定的范围,就返回的就是指定的范围 //如果将来的文字范围小于指定的范围,就返回实际的范围 CGSize maxsize=CGSizeMake(MAXFLOAT, MAXFLOAT); CGSize namesize=[self sizeWithString:_weibo.name font:SLFontNiCheng maxSize:maxsize]; // CGRect namesize= [_weibo.name boundingRectWithSize:maxsize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil]; CGFloat nichengH=namesize.height; CGFloat nichengW=namesize.width; CGFloat nichengY=(self.iconF.size.height-nichengH)*0.5+iconViewY; self.nichengF=CGRectMake(nichengX , nichengY, nichengW,nichengH); //3设置vip的frame CGFloat vipViewX=CGRectGetMaxX(self.nichengF)+padding; CGFloat vipViewY=nichengY; CGFloat vipViewW=14; CGFloat vipViewH=14; self.vipF=CGRectMake(vipViewX, vipViewY, vipViewW, vipViewH); //4设置正文的frame CGFloat zhengwenX=iconViewX; CGFloat zhengwenY=CGRectGetMaxY(self.iconF)+padding; CGSize maxsize1=CGSizeMake(300, MAXFLOAT); CGSize zhengwensize=[self sizeWithString:_weibo.text font:SLFontZhengWen maxSize:maxsize1]; CGFloat zhengwenW=zhengwensize.width; CGFloat zhengwenH=zhengwensize.height; self.zhengwenF=CGRectMake(zhengwenX, zhengwenY, zhengwenW, zhengwenH); //5设置配图的frame // CGFloat cellHeight=0; if (_weibo.picture) { CGFloat peituX=iconViewX; CGFloat peituY=CGRectGetMaxY(self.zhengwenF)+padding; CGFloat peituW=100; CGFloat peituH=100; self.peituF=CGRectMake(peituX, peituY, peituW, peituH); self.cellHeight=CGRectGetMaxY(self.peituF)+padding; }else { //无配图的情况下的行高 self.cellHeight=CGRectGetMaxY(self.zhengwenF)+padding; } } /** * 计算文本的宽高 * * @param str 文本显示 * @param font 文本显示的字体 * @param maxSize 文本显示的此存 * * @return */ -(CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize { NSDictionary *dict=@{NSFontAttributeName: font}; CGSize nasize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size; return nasize; } @end
最终实现效果图如下:
以上方法,即是利用代码进行对UITableViewCell进行的重写,下一讲讲解关于
利用xib创建重用的单元格对象。
相关文章推荐
- IOS开发UI篇--UITableView的自定义布局==xib布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- iOS开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- iOS开发UI篇—实现UItableview控件数据刷新
- iOS开发UI篇—在UItableview中实现加载更多功能
- iOS开发UI篇—在UItableview中实现加载更多功能
- iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建
- iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)
- iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一)
- 学习IOS开发UI篇--UITableView中Cell的创建方式总结
- IOS开发之TableView、多个TableViewCell、自定义Cell、Cell上画画(故事板+代码方式)
- iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建