IOS开发UI篇--UITableView的自定义布局==纯代码布局

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

UITableView中除了利用系统的UItableViewCell不能完成需求进行布局时,还可以进行自定义布局;

自定义布局分为两类:(1)利用代码进行创建

(2)利用xib进行实现;

下面对利用代码进行创建分析:

应用场景:像微博,等列表数据展示(由于微博的每个单元格的数据大小不一致,所以得计算每个单元格的大小)

分析:前提是获取列表数据,然后建立每个单元格的模型(建立单元格模型应继承UITableViewCell)复写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

此方法即可,在此方法中添加单元格所需要的各个视图控件, 然后根据微博对象模型,确定每个控件的位置,并进行数据

的填充,

主要在此方法中几个重要的方法:(特别是方法的执行顺序)1.-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath2.-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

下面以一个例子进行说明:

由于本案例整个界面就是单独的一个UITableView,故而主控制器设置成UITableViewController;这样可以减少很多连线问题,

因为UITableViewController里面已进行关联,且内部也开放出来了tableview;可以直接使用

(1)下面是一个SLViewController.m文件

1#import"SLViewController.h"23#import"SLWeiBo.h"4#import"SLWeiBoCell.h"5#import"SLWeiBoFrame.h"67@interfaceSLViewController ()89//定义数组,保存模型数据10@PRoperty (nonatomic,strong)NSArray *statusFrames;1112@end1314@implementationSLViewController1516- (void)viewDidLoad17{18[super viewDidLoad];19self.tableView ;20}2122#pragmamark -懒加载23-(NSArray *)statusFrames24{25if(_statusFrames==nil) {26//加载plist数据文件27NSString *fullpath=[[NSBundle mainBundle] pathForResource:@"statuses"ofType:@"plist"];28NSArray *arr=[NSArray arrayWithContentsOfFile:fullpath];29NSMutableArray *mutearr=[NSMutableArray arrayWithCapacity:arr.count];30for(NSDictionary *dictinarr) {31//字典转模型,传进去一个字典,返回一个微博模型32SLWeiBo *weibo=[SLWeiBo weiBoWithDict:dict];33//计算每一个表格的高度并保存34SLWeiBoFrame *weiboframe=[[SLWeiBoFrame alloc] init];35weiboframe.weibo=weibo;36//把Frame模型保存到数组中37[mutearr addObject:weiboframe];38}3940self.statusFrames=[mutearr mutableCopy];41}42return_statusFrames;43}4445#pragmamark -实现数据源方法46/**47* tableview中返回一共有多少组,有一组的话,可以省略不写48*49* @param tableView50*51* @return 返回有多少组52*/53-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView54{55return1;56}57/**58* tableview返回一共有多少个单元格59*60* @param tableView61* @param section 第几组62*63* @return 某组有多少单元格64*/65-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section66{67returnself.statusFrames.count;68}6970/**71* tableView返回每个单元格的对象72*73* @param tableView74* @param indexPath 保存有该对象是第几组,第几个单元格75*76* @return 返回每个单元格对象77*/78-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath79{80//1.从缓存中取数据81staticNSString *identifier=@"status";82SLWeiBoCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];83//2创建表格84if(cell==nil) {85cell=[[SLWeiBoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];86}87//3设置数据88SLWeiBoFrame *frame=self.statusFrames[indexPath.row];89cell.itemframe=frame;90returncell;91}92#pragmamark -实现高度的代理方法93/**94* 计算每个单元格的高度95*96* @param tableView97* @param indexPath 该单元格是某组某行的单元格98*99* @return 返回该单元格的高度100*/101-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath102{103SLWeiBoFrame *frame=self.statusFrames[indexPath.row];104returnframe.cellHeight;105}106/**107* 设置是否显示状态栏108*109* @return 返回YES,不显示,返回NO,显示110*/111-(BOOL)prefersstatusBarHidden112{113returnNO;114}115@end

(2)这个SLWeiBo.H与SLWeiBo.m Global.h文件

第一个文件是定义一些基本属性,用来进行字典转换模型;并定义了两个方法,一个是类方法,一个实例方法,在第二个文件中进行实现

第三个文件是对第一个和第二个文件的定义方法进行的抽取,方便重用,第三个文件利用定义宏进行代码抽取,

1#import"Global.h"2/**3* 创建一个微博对象,保存模型数据4*/5@interfaceSLWeiBo : NSObject67@property (nonatomic,copy) NSString *text;//内容8@property (nonatomic,copy) NSString *icon;//头像9@property (nonatomic,copy) NSString *name;//昵称10@property (nonatomic,copy) NSString *picture;//配图11//是否是vip12@property (nonatomic,assign) BOOL vip;1314initWeiBo(weiBo)15////进行转换的实例方法16//-(instancetype)initWithWeiBo:(NSDictionary *)dict;17//// 进行转换的类方法18//+(instancetype)weiBoWithDict:(NSDictionary *)dict;1920@end

1#import"SLWeiBo.h"23@implementationSLWeiBo45//分别对类方法和实例方法进行实现6weiBoInitDict(weiBo);7//-(instancetype)initWithWeiBo:(NSDictionary *)dict;8//{9//if (self=[super init]) {10//[self setValuesForKeysWithDictionary:dict];11//}12//return self;13//}14//15//+(instancetype)weiBoWithDict:(NSDictionary *)dict16//{17//return [[self alloc] initWithWeiBo:dict];18//}1920@end

1#ifndef ___Global_h2#define___Global_h34#defineinitWeiBo(name)\5-(instancetype) initWithWeiBo:(NSDictionary *)dict;\6+(instancetype) name##WithDict:(NSDictionary *)dict;78#defineweiBoInitDict(name)\9-(instancetype) initWithWeiBo:(NSDictionary *)dict;\10{\11if(self=[super init]) {\12[self setValuesForKeysWithDictionary:dict];\13}\14returnself;\15}\16+(instancetype) name##WithDict:(NSDictionary *)dict\17{\18return[[self alloc] initWithWeiBo:dict];\19}20#endif

(3)SLWeiBoCell.h和SLWeiBoCell.m文件是继承自UITableViewCell的,是对UITableViewCell进行的重写,已到达所需要的要求界面,

并设置数据,与设置位置。

1#import<UIKit/UIKit.h>2@classSLWeiBoFrame;34@interfaceSLWeiBoCell : UITableViewCell5//导入SLweiboFrame对象,保存着一个单元格里面每个控件的位置,及weibo对象6@property (nonatomic,strong) SLWeiBoFrame *itemframe;78@end

1#import"SLWeiBoCell.h"23#import"SLWeiBoFrame.h"45#defineSLFontNiCheng [UIFont systemFontOfSize:15]6#defineSLFontZhengWen [UIFont systemFontOfSize:16]7@interfaceSLWeiBoCell()8//头部头像9@property (nonatomic,weak) UIImageView *iconheader;10//昵称11@property (nonatomic,weak) UILabel *nicheng;12//是否是vip13@property (nonatomic,weak) UIImageView *vip;14//正文显示15@property (nonatomic,weak) UILabel *zhengwen;16//配图显示17@property (nonatomic,weak) UIImageView *peitu;1819@end2021@implementationSLWeiBoCell2223//复写此方法,以达到重写UITableViewCell的目的24- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier25{26self =[super initWithStyle:style reuseIdentifier:reuseIdentifier];27if(self) {28//让自定义cell和系统的cell一样,创建出来就拥有一些子控件提供给我们使用29//1.创建头像30UIImageView *iconheader=[[UIImageView alloc] init];31[self.contentView addSubview:iconheader];32self.iconheader=iconheader;33//2.创建昵称34UILabel *nicheng=[[UILabel alloc] init];35nicheng.font=SLFontNiCheng;36[self.contentView addSubview:nicheng];37self.nicheng=nicheng;38//3.创建vip39UIImageView *vip=[[UIImageView alloc] init];40vip.image=[UIImage imageNamed:@"vip"];41[self.contentView addSubview:vip];42self.vip=vip;43//4创建正文44UILabel *zhengwen=[[UILabel alloc] init];45//让正文进行多行显示46zhengwen.numberOfLines=0;47//设置正文的字体,此时的字体应该在和计算该正文的字体长宽所用字体一致,48zhengwen.font=SLFontZhengWen;49[self.contentView addSubview:zhengwen];5051self.zhengwen=zhengwen;52//5创建配图53UIImageView *peitu=[[UIImageView alloc] init];54[self.contentView addSubview:peitu];55self.peitu=peitu;56}57returnself;58}59-(void)setItemframe:(SLWeiBoFrame *)itemframe60{61_itemframe=itemframe;62//设置数据63[self settingData];64//设置frame65[self settingFrame];66}6768-(void)settingData69{70//设置头像71SLWeiBo *weibof=self.itemframe.weibo;72self.iconheader.image=[UIImage imageNamed:weibof.icon];73//设置昵称74self.nicheng.text=weibof.name;75//设置vip76if(weibof.vip) {77self.nicheng.textColor=[UIColor redColor];78self.vip.hidden=NO;79}else{80self.nicheng.textColor=[UIColor blackColor];81self.vip.hidden=YES;82}83//设置内容84self.zhengwen.text=weibof.text;85//设置配图86if(weibof.picture) {87self.peitu.image=[UIImage imageNamed:weibof.picture];88self.peitu.hidden=NO;89}else{90self.peitu.hidden=YES;91}92}9394-(void)settingFrame95{96//1设置头像的frame97self.iconheader.frame=self.itemframe.iconF;98//2设置昵称的frame99self.nicheng.frame=self.itemframe.nichengF;100//3设置vip的frame101self.vip.frame=self.itemframe.vipF;102//4设置正文的frame103self.zhengwen.frame=self.itemframe.zhengwenF;104//5设置配图的frame105if(self.itemframe.weibo.picture) {106self.peitu.frame=self.itemframe.peituF;107}108}109@end

(4)SLWeiBoFrame.h和SLWeiBoFrame.m 文件是为了求行高而进行的数据抽取,即先计算出行的高,并且保存每行中控件的位置;

方便传给cell进行利用;

1#import"SLWeiBo.h"2@interfaceSLWeiBoFrame : NSObject34/**5头像的frame6*/7@property (nonatomic,assign) CGRect iconF;8/**9昵称的frame10*/11@property (nonatomic,assign) CGRect nichengF;12/**13vip的frame14*/15@property (nonatomic,assign) CGRect vipF;16/**17正文的frame18*/19@property (nonatomic,assign) CGRect zhengwenF;20/**21配图的frame22*/23@property (nonatomic,assign) CGRect peituF;24/**25行高26*/27@property (nonatomic,assign) CGFloat cellHeight;28@property (nonatomic,strong) SLWeiBo *weibo;2930@end

1#import"SLWeiBoFrame.h"2#import"SLWeiBo.h"3#defineSLFontNiCheng [UIFont systemFontOfSize:15]4#defineSLFontZhengWen [UIFont systemFontOfSize:16]5@implementationSLWeiBoFrame678-(void)setWeibo:(SLWeiBo *)weibo9{1011_weibo=weibo;12//间隙13CGFloat padding=10;14//1设置头像的frame15CGFloat iconViewX=padding;16CGFloat iconViewY=padding;17CGFloat iconViewW=30;18CGFloat iconViewH=30;19self.iconF=CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH);2021//2设置昵称的frame22CGFloat nichengX=CGRectGetMaxX(self.iconF)+padding;23/**24* attributes 告诉系统文字的大小25*/26//NSDictionary *dict=@{NSFontAttributeName:[UIFont systemFontOfSize:15]};2728//如果将来计算的文字的范围超出了指定的范围,就返回的就是指定的范围29//如果将来的文字范围小于指定的范围,就返回实际的范围30CGSize maxsize=CGSizeMake(MAXFLOAT, MAXFLOAT);31CGSize namesize=[self sizeWithString:_weibo.name font:SLFontNiCheng maxSize:maxsize];32//CGRect namesize= [_weibo.name boundingRectWithSize:maxsize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];3334CGFloat nichengH=namesize.height;35CGFloat nichengW=namesize.width;3637CGFloat nichengY=(self.iconF.size.height-nichengH)*0.5+iconViewY;38self.nichengF=CGRectMake(nichengX , nichengY, nichengW,nichengH);394041//3设置vip的frame42CGFloat vipViewX=CGRectGetMaxX(self.nichengF)+padding;43CGFloat vipViewY=nichengY;44CGFloat vipViewW=14;45CGFloat vipViewH=14;46self.vipF=CGRectMake(vipViewX, vipViewY, vipViewW, vipViewH);474849//4设置正文的frame5051CGFloat zhengwenX=iconViewX;52CGFloat zhengwenY=CGRectGetMaxY(self.iconF)+padding;5354CGSize maxsize1=CGSizeMake(300, MAXFLOAT);55CGSize zhengwensize=[self sizeWithString:_weibo.text font:SLFontZhengWen maxSize:maxsize1];56CGFloat zhengwenW=zhengwensize.width;57CGFloat zhengwenH=zhengwensize.height;5859self.zhengwenF=CGRectMake(zhengwenX, zhengwenY, zhengwenW, zhengwenH);60//5设置配图的frame61//CGFloat cellHeight=0;62if(_weibo.picture) {63CGFloat peituX=iconViewX;64CGFloat peituY=CGRectGetMaxY(self.zhengwenF)+padding;65CGFloat peituW=100;66CGFloat peituH=100;67self.peituF=CGRectMake(peituX, peituY, peituW, peituH);68self.cellHeight=CGRectGetMaxY(self.peituF)+padding;69}else70{71//无配图的情况下的行高72self.cellHeight=CGRectGetMaxY(self.zhengwenF)+padding;73}74}7576/**77* 计算文本的宽高78*79* @param str 文本显示80* @param font 文本显示的字体81* @param maxSize 文本显示的此存82*83* @return84*/85-(CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize86{87NSDictionary *dict=@{NSFontAttributeName: font};88CGSize nasize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;89returnnasize;90}9192@end

最终实现效果图如下:

以上方法,即是利用代码进行对UITableViewCell进行的重写,下一讲讲解关于

利用xib创建重用的单元格对象。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航