一、UITableViewCell的自定義
UITableVie中系統的Cell共提供了四種默認樣式,
分別是:
UITableVieCellStyleDefault //只有一個label
UITableVieCellStyleValue1 //兩個label
UITableVieCellStyleValue2 //兩個label,佈局不同於上面的
UITableVieCellStyleSubtitle //帶副標題
但是在實際使⽤用過程中,Cell樣式的佈局上千差萬別,
比如:
沒錯,聊天界面也是TableViewCell。
爲了滿足各種奇葩的需求和精美的設計,需要我們自定義cell
我們也就可以在一個tableView裏放各種不同的Cell
方法也不復雜
首先創建一個繼承於UITableViewCell的類CustomCell
在CustomCell.h中聲明屬性,這些屬性就是要添加到自定義cell上的Label,ImageView等等
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell
@property (nonatomic,retain)UILabel* nameLabel;//顯示名字
@end
然後在CustomCell.m中對聲明對屬性寫好懶加載
#import "CustomCell.h"
@implementation CustomCell
//姓名標籤的初始化
-(UILabel *)nameLabel
{
if (!_nameLabel) {
_nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(80, 10, 120, 30)];
[self.contentView addSubview:_nameLabel];
}
return _nameLabel;
}
@end
最後在UITableView的註冊單元格和填充單元格的代碼中替換系統的UITableViewCell
//註冊單元格,在ViewDidLoad方法中
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CELL"];
//重用隊列,這在單元格填充的方法內
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//這裏用CustomCell替換原來的UITableViewCell
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];
}總體思路就是這樣,主要不同是這個cell怎麼自定義,裏面加多少label,imageView,怎麼佈局,就是個人的事了。
二、cell高度的自適應
有時候要根據內容調整cell的高度,要用到cell返回高度的代理方法
//返回高度的代理方法
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
還需要對內容的高度進行一定的計算,這裏先提供一種計算文本寬高的方法
這是一個自寫函數,核心是使用了系統的boundingRectWithSize:CGSizeMake(width,height) optins:() attributes:()context:方法
這個方法需要我們提供一個寬度一個高度,如果寬度設置爲MaxFloat,高度給定,則最後計算出一個CGRect會根據內容content計算出相應的寬度。
同樣,如果高度設置爲MaxFloat,最後會計算出一個CGRect,其高度是根據content計算出的
options:這個參數比較重要
1.NSStringDrawingUsesLineFragmentOrigin:
繪製文本時使用 line fragement origin 而不是 baseline origin。
2.NSStringDrawingUsesFontLeading:
計算行高時使用行距。(字體大小+行間距=行距)
3.NSStringDrawingTruncatesLastVisibleLine:
如果文本內容超出指定的矩形限制,文本將被截去並在最後一個字符後加上省略號。如果沒有指定NSStringDrawingUsesLineFragmentOrigin選項,則該選項被忽略。
4.計算佈局時使用圖元字形(而不是印刷字體)。
Use the image glyph bounds (instead of the typographic bounds) when computing layout.
1.NSKernAttributeName: @10 調整字句 kerning 字句調整
2.NSFontAttributeName : [UIFont systemFontOfSize:_fontSize] 設置字體
3.NSForegroundColorAttributeName :[UIColor redColor] 設置文字顏色
4.NSParagraphStyleAttributeName : paragraph 設置段落樣式
5.NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.alignment = NSTextAlignmentCenter;
6.NSBackgroundColorAttributeName: [UIColor blackColor] 設置背景顏色
7.NSStrokeColorAttributeName設置文字描邊顏色,需要和NSStrokeWidthAttributeName設置描邊寬度,這樣就能使文字空心.
context:上下文。包括一些信息,例如如何調整字間距以及縮放。最終,該對象包含的信息將用於文本繪製。但是沒用過,還不懂,該參數可爲 nil 。
#pragma mark -- 計算寬窄的函數
-(float)autoCalculateWidthOrHeight:(float)height
width:(float)width
fontsize:(float)fontsize
content:(NSString*)content
{
//計算出rect
CGRect rect = [content boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontsize]} context:nil];
//判斷計算的是寬還是高
if (height == MAXFLOAT) {
return rect.size.height;
}
else
return rect.size.width;
}
有了上面這個看起來有點複雜的方法,我們就可以調用它計算出應有的寬或者高了
//計算出nameLabel的寬度,高度爲20,字體大小爲17
_nameWidth = [self autoCalculateWidthOrHeight:20 width:MAXFLOAT fontsize:17 content:name];
//
// RootTableViewController.m
#import "RootTableViewController.h"
#import "CustomTableViewCell.h"
@interface RootTableViewController ()
@property (nonatomic,retain)NSArray *contentArray;
@end
@implementation RootTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"自定義cell";
//註冊cell
[self.tableView registerClass:[CustomTableViewCell class] forCellReuseIdentifier:@"CELL"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Incomplete implementation, return the number of sections
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete implementation, return the number of rows
return 3;
}
#pragma mark -- 單元格填充
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];
cell.tag =1000;
//對cell填寫內容
cell.newsImageView.image = [UIImage imageNamed:@"placeholder.jpg"];
cell.titleLabel.text = [NSString stringWithFormat:@"第%ld條",indexPath.row];
cell.abstractLabel.text = _contentArray[indexPath.row];
cell.commentNumLavel.text = @"1.6萬跟帖";
return cell;
}
//返回單元格的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//數據數組
_contentArray = [[NSArray alloc]initWithObjects:@"不信這都不過。我是高二的文科生,政治學得不怎麼樣,
老爸就叫我抄了老師的號碼說是跟老師探討怎麼督促我學習什麼的…。結果兩個月後,政治老師被我爸拿下了………。- -!我現在更不知道政治該怎麼辦……。 ",
@"聽我們這的一位老師傅講的。。。前面一輛寶馬,開車的是個妹子,後面跟着一個皮卡,塊紅綠燈了,到路口,剛好黃燈,那妹子直接剎車,當然了,你們懂的,
皮卡沒反應過來,再加上剎車不如人寶馬快,果斷撞上了,其實要是個爺們開那寶馬,黃燈也就闖過去了,那皮卡就這麼想的。然後那妹子走下車來,看車撞了,
蹲地上就哭。那皮卡里的少年出來愣了,扶着那妹子說,妹妹你別哭了,該哭的是我。。。 ",@"剛剛從臺灣旅游回來,體會到了傳說中的民風淳樸。。。。。
默默地分割。。。。。。話說住在嘉義那天去夜市,找了一家店吃宵夜,點了一個特色的火雞飯和滷肉飯,小碗那種,總共才40臺幣,十塊rmb都不到,
中途我出去買鹽酥雞,我朋友出去買飲料,吃完我們就抹抹嘴巴走了(我們都以爲對方付過錢了)走到半路想起來落了圍巾,回去拿,我跟店員打了招呼,
拿好圍巾出店門,想想不對,問朋友付錢沒?她也搖頭,於是回到店裏問那個靦腆的小夥子,怎麼不問我們收錢,他說:看你們剛剛走得急。。。", nil];
//根據內容計算高度
CGRect rect = [_contentArray[indexPath.row] boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.view.frame)-120, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17]} context:nil];
//再加上其他控件的高度得到cell的高度
return rect.size.height + 20 + 20;
}
@end
自定義的cell
//
// CustomTableViewCell.h
#import <UIKit/UIKit.h>
@interface CustomTableViewCell : UITableViewCell
//創建三個label,一個imageView
@property (nonatomic,retain)UILabel* titleLabel;//標題
@property (nonatomic,retain)UILabel* abstractLabel;//摘要
@property (nonatomic,retain)UILabel* commentNumLavel;//跟帖數量
@property (nonatomic,retain)UIImageView* newsImageView;//新聞圖片
@end
//
// CustomTableViewCell.m
#import "CustomTableViewCell.h"
@implementation CustomTableViewCell
#pragma mark -- 懶加載
//左側圖片
-(UIImageView *)newsImageView
{
if (!_newsImageView) {
_newsImageView = [[UIImageView alloc]initWithFrame:CGRectMake(5, 10, 80, 80)];
[self.contentView addSubview:_newsImageView];
_newsImageView.image = [UIImage imageNamed:@"placeholder.jpg"];
//設置圓角
_newsImageView.layer.cornerRadius = 5;
_newsImageView.layer.masksToBounds = YES;
}
return _newsImageView;
}
//標題
-(UILabel *)titleLabel
{
if (!_titleLabel) {
_titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 5, CGRectGetWidth(self.frame)-120, 20)];
[self.contentView addSubview:_titleLabel];
_titleLabel.backgroundColor = [UIColor colorWithRed:247/255.0 green:162/255.0 blue:120/255.0 alpha:1];
}
return _titleLabel;
}
//摘要
-(UILabel *)abstractLabel
{
if (!_abstractLabel) {
_abstractLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 25, CGRectGetWidth(self.frame)-120, 70)];
[self.contentView addSubview:_abstractLabel];
_abstractLabel.backgroundColor = [UIColor colorWithRed:200/255.0 green:233/255.0 blue:160/255.0 alpha:1];
//設置行數,這裏很重要,0意味着行數自適應
_abstractLabel.numberOfLines = 0;
//設置字體
_abstractLabel.font = [UIFont fontWithName:@"28=蒙納幼雅麗" size:15];
}
//根據cell重新調整label的高度
CGRect labelRect = _abstractLabel.frame;
labelRect.size.height = CGRectGetHeight(self.frame)-20-20;
_abstractLabel.frame = labelRect;
return _abstractLabel;
}
//跟帖數
-(UILabel *)commentNumLavel
{
if (!_commentNumLavel) {
_commentNumLavel = [[UILabel alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.frame)-100,
CGRectGetHeight(self.frame)-20, 80, 15)];
[self.contentView addSubview:_commentNumLavel];
_commentNumLavel.backgroundColor = [UIColor colorWithRed:109/255.0 green:211/255.0 blue:206/255.0 alpha:1];
//設置字體
_commentNumLavel.font = [UIFont fontWithName:@"testfont" size:12];
}
return _commentNumLavel;
}
@end
效果
三、在可視化下讓cell自適應高度
在使用xib或者storyBoard時,同樣可以在heightForCell的代理方法裏調整cell的高度
但是cell上面的label要同時改變大小,就有所不同。
可以使用拉約束的方法,如圖我這裏是一個UITableViewCell的xib文件,給上面的contentLabel拉了四個約束,具體怎麼拉看autolayout
分別規定了這個Label 到cell上邊緣的距離,到cell下邊緣的距離,到cell左邊緣的距離,已經label的width給定值。
這樣,cell的高度變化,label爲隨之變化