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


    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 *)indexPath
    102 {
    103     SLWeiBoFrame *frame=self.statusFrames[indexPath.row];
    104         return frame.cellHeight;
    105 }
    106 /**
    107  *  设置是否显示状态栏
    108  *
    109  *  @return 返回YES,不显示,返回NO,显示
    110  */
    111 -(BOOL)prefersStatusBarHidden
    112 {
    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 //是否是vip
    12 @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 *)dict
    16 //{
    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 : UITableViewCell
    5 //导入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的frame
    101     self.vip.frame=self.itemframe.vipF;
    102     //4设置正文的frame
    103     self.zhengwen.frame=self.itemframe.zhengwenF;
    104     //5设置配图的frame
    105     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 昵称的frame
    10  */
    11 @property (nonatomic,assign) CGRect nichengF;
    12 /**
    13 vip的frame
    14  */
    15 @property (nonatomic,assign) CGRect vipF;
    16 /**
    17  正文的frame
    18  */
    19 @property (nonatomic,assign) CGRect zhengwenF;
    20 /**
    21 配图的frame
    22  */
    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设置头像的frame
    15     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设置昵称的frame
    22     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的frame
    42     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设置正文的frame
    50     
    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设置配图的frame
    61     //   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     }else
    70     {
    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  *  @return
    84  */
    85 -(CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
    86 {
    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创建重用的单元格对象。

  • 相关阅读:
    唯一的确定一棵二叉树
    Educational Codeforces Round 55 (Rated for Div. 2)
    524 (Div. 2) Masha and two friends
    单链表实现n(n≥20)的阶乘
    表达式的后缀表示
    UPCOJ2012 The King’s Walk(dp)
    第七届山东省省赛D Swiss-system tournament(归并排序)
    第七届山东省省赛C Proxy(最短路)
    hihocoder1185 连通性·三
    hihocoder1184 连通性二·边的双连通分量
  • 原文地址:https://www.cnblogs.com/android-victor/p/3759977.html
Copyright © 2020-2023  润新知