首页 > 学院 > 开发设计 > 正文

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

2019-11-14 20:27:24
字体:
来源:转载
供稿:网友

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

自定义布局分为两类:(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文件

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

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

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

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

 1 #import "Global.h" 2 /** 3  *  创建一个微博对象,保存模型数据 4  */ 5 @interface SLWeiBo : NSObject 6  7 @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;13 14 initWeiBo(weiBo)15 ////进行转换的实例方法16 //-(instancetype)initWithWeiBo:(NSDictionary *)dict;17 //// 进行转换的类方法18 //+(instancetype)weiBoWithDict:(NSDictionary *)dict;19 20 @end
 1 #import "SLWeiBo.h" 2  3 @implementation SLWeiBo 4  5 //分别对类方法和实例方法进行实现 6 weiBoInitDict(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 //}19 20 @end
 1 #ifndef ___Global_h 2 #define ___Global_h 3    4 #define initWeiBo(name)/ 5 -(instancetype) initWithWeiBo:(NSDictionary *)dict;/ 6 +(instancetype) name##WithDict:(NSDictionary *)dict; 7  8 #define weiBoInitDict(name)/ 9 -(instancetype) initWithWeiBo:(NSDictionary *)dict;/10 {/11     if (self=[super init]) {/12         [self setValuesForKeysWithDictionary:dict];/13     }/14     return self;/15 }/16 +(instancetype) name##WithDict:(NSDictionary *)dict/17 {/18     return [[self alloc] initWithWeiBo:dict];/19 }20 #endif

 

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

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

1 #import <UIKit/UIKit.h>2 @class SLWeiBoFrame;3 4 @interface SLWeiBoCell : UITableViewCell5 //导入SLweiboFrame对象,保存着一个单元格里面每个控件的位置,及weibo对象6 @property (nonatomic,strong) SLWeiBoFrame *itemframe;7 8 @end
  1 #import "SLWeiBoCell.h"  2   3 #import "SLWeiBoFrame.h"  4   5 #define SLFontNiCheng [UIFont systemFontOfSize:15]  6 #define SLFontZhengWen [UIFont systemFontOfSize:16]  7 @interface SLWeiBoCell()  8 //头部头像  9 @property (nonatomic,weak) UIImageView *iconheader; 10 //昵称 11 @property (nonatomic,weak) UILabel *nicheng; 12 //是否是vip 13 @property (nonatomic,weak) UIImageView *vip; 14 //正文显示 15 @property (nonatomic,weak) UILabel *zhengwen; 16 //配图显示 17 @property (nonatomic,weak) UIImageView *peitu; 18  19 @end 20  21 @implementation SLWeiBoCell 22  23 //复写此方法,以达到重写UITableViewCell的目的 24 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 25 { 26     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 27     if (self) { 28         // 让自定义cell和系统的cell一样,创建出来就拥有一些子控件提供给我们使用 29         //1.创建头像 30         UIImageView *iconheader=[[UIImageView alloc] init]; 31         [self.contentView addSubview:iconheader]; 32         self.iconheader=iconheader; 33         //2.创建昵称 34         UILabel *nicheng=[[UILabel alloc] init]; 35         nicheng.font=SLFontNiCheng; 36         [self.contentView addSubview:nicheng]; 37         self.nicheng=nicheng; 38         //3.创建vip 39         UIImageView *vip=[[UIImageView alloc] init]; 40         vip.image=[UIImage imageNamed:@"vip"]; 41         [self.contentView addSubview:vip]; 42         self.vip=vip; 43         //4创建正文 44         UILabel *zhengwen=[[UILabel alloc] init]; 45         //让正文进行多行显示 46         zhengwen.numberOfLines=0; 47         //设置正文的字体,此时的字体应该在和计算该正文的字体长宽所用字体一致, 48         zhengwen.font=SLFontZhengWen; 49         [self.contentView addSubview:zhengwen]; 50          51         self.zhengwen=zhengwen; 52         //5创建配图 53         UIImageView *peitu=[[UIImageView alloc] init]; 54         [self.contentView addSubview:peitu]; 55         self.peitu=peitu; 56     } 57     return self; 58 } 59 -(void)setItemframe:(SLWeiBoFrame *)itemframe 60 { 61     _itemframe=itemframe; 62     //设置数据 63     [self settingData]; 64     //设置frame 65     [self settingFrame]; 66 } 67  68 -(void)settingData 69 { 70     //设置头像 71     SLWeiBo *weibof=self.itemframe.weibo; 72     self.iconheader.image=[UIImage imageNamed:weibof.icon]; 73     //设置昵称 74     self.nicheng.text=weibof.name; 75     //设置vip 76     if (weibof.vip) { 77         self.nicheng.textColor=[UIColor redColor]; 78         self.vip.hidden=NO; 79     }else{ 80         self.nicheng.textColor=[UIColor blackColor]; 81         self.vip.hidden=YES; 82     } 83     //设置内容 84     self.zhengwen.text=weibof.text; 85     //设置配图 86     if (weibof.picture) { 87         self.peitu.image=[UIImage imageNamed:weibof.picture]; 88         self.peitu.hidden=NO; 89     }else{ 90         self.peitu.hidden=YES; 91     } 92 } 93  94 -(void)settingFrame 95 { 96     //1设置头像的frame 97     self.iconheader.frame=self.itemframe.iconF; 98     //2设置昵称的frame 99     self.nicheng.frame=self.itemframe.nichengF;100     //3设置vip的frame101     self.vip.frame=self.itemframe.vipF;102     //4设置正文的frame103     self.zhengwen.frame=self.itemframe.zhengwenF;104     //5设置配图的frame105     if (self.itemframe.weibo.picture) {106         self.peitu.frame=self.itemframe.peituF;107     }108 }109 @end

 

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

方便传给cell进行利用;

 1 #import "SLWeiBo.h" 2 @interface SLWeiBoFrame : NSObject 3  4 /** 5  头像的frame 6  */ 7 @property (nonatomic,assign) CGRect iconF; 8 /** 9 昵称的frame10  */11 @property (nonatomic,assign) CGRect nichengF;12 /**13 vip的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;29 30 @end
 1 #import "SLWeiBoFrame.h" 2 #import "SLWeiBo.h" 3 #define SLFontNiCheng [UIFont systemFontOfSize:15] 4 #define SLFontZhengWen [UIFont systemFontOfSize:16] 5 @implementation SLWeiBoFrame 6  7  8 -(void)setWeibo:(SLWeiBo *)weibo 9 {10 11     _weibo=weibo;12     //间隙13     CGFloat padding=10;14     //1设置头像的frame15     CGFloat iconViewX=padding;16     CGFloat iconViewY=padding;17     CGFloat iconViewW=30;18     CGFloat iconViewH=30;19     self.iconF=CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH);20     21     //2设置昵称的frame22     CGFloat nichengX=CGRectGetMaxX(self.iconF)+padding;23     /**24      * attributes 告诉系统文字的大小25      */26     // NSDictionary *dict=@{NSFontAttributeName:[UIFont systemFontOfSize:15]};27     28     // 如果将来计算的文字的范围超出了指定的范围,就返回的就是指定的范围29     //如果将来的文字范围小于指定的范围,就返回实际的范围30     CGSize maxsize=CGSizeMake(MAXFLOAT, MAXFLOAT);31     CGSize namesize=[self  sizeWithString:_weibo.name font:SLFontNiCheng maxSize:maxsize];32     //    CGRect namesize= [_weibo.name boundingRectWithSize:maxsize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];33     34     CGFloat nichengH=namesize.height;35     CGFloat nichengW=namesize.width;36     37     CGFloat nichengY=(self.iconF.size.height-nichengH)*0.5+iconViewY;38     self.nichengF=CGRectMake(nichengX , nichengY, nichengW,nichengH);39     40     41     //3设置vip的frame42     CGFloat vipViewX=CGRectGetMaxX(self.nichengF)+padding;43     CGFloat vipViewY=nichengY;44     CGFloat vipViewW=14;45     CGFloat vipViewH=14;46     self.vipF=CGRectMake(vipViewX, vipViewY, vipViewW, vipViewH);47     48     49     //4设置正文的frame50     51     CGFloat zhengwenX=iconViewX;52     CGFloat zhengwenY=CGRectGetMaxY(self.iconF)+padding;53     54     CGSize maxsize1=CGSizeMake(300, MAXFLOAT);55     CGSize zhengwensize=[self sizeWithString:_weibo.text font:SLFontZhengWen maxSize:maxsize1];56     CGFloat zhengwenW=zhengwensize.width;57     CGFloat zhengwenH=zhengwensize.height;58     59     self.zhengwenF=CGRectMake(zhengwenX, zhengwenY, zhengwenW, zhengwenH);60     //5设置配图的frame61     //   CGFloat cellHeight=0;62     if (_weibo.picture) {63         CGFloat peituX=iconViewX;64         CGFloat peituY=CGRectGetMaxY(self.zhengwenF)+padding;65         CGFloat peituW=100;66         CGFloat peituH=100;67         self.peituF=CGRectMake(peituX, peituY, peituW, peituH);68         self.cellHeight=CGRectGetMaxY(self.peituF)+padding;69     }else70     {71         //无配图的情况下的行高72         self.cellHeight=CGRectGetMaxY(self.zhengwenF)+padding;73     }74 }75 76 /**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 {87     NSDictionary *dict=@{NSFontAttributeName: font};88     CGSize  nasize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;89     return nasize;90 }91 92 @end

最终实现效果图如下:

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

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表