IOS開發UI篇--UITableView的自定義佈局==純代碼佈局

UITableView中除了利用系統的UItableViewCell不能完成需求進行佈局時,還能夠進行自定義佈局;數組

自定義佈局分爲兩類:(1)利用代碼進行建立緩存

(2)利用xib進行實現;ide

下面對利用代碼進行建立分析:佈局

應用場景:像微博,等列表數據展現(因爲微博的每一個單元格的數據大小不一致,因此得計算每一個單元格的大小)
    分析:前提是獲取列表數據,而後創建每一個單元格的模型(創建單元格模型應繼承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;這樣能夠減小不少連線問題,atom

由於UITableViewController裏面已進行關聯,且內部也開放出來了tableview;能夠直接使用spa

(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文件code

第一個文件是定義一些基本屬性,用來進行字典轉換模型;並定義了兩個方法,一個是類方法,一個實例方法,在第二個文件中進行實現對象

第三個文件是對第一個和第二個文件的定義方法進行的抽取,方便重用,第三個文件利用定義宏進行代碼抽取,

 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建立重用的單元格對象。

相關文章
相關標籤/搜索