iOS個人整理20-UITableViewCell自定義,cell高度的自適應(純代碼)

一、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.


attributes:文本屬性,一個字典,裏面包含了文字的各種屬性,這裏沒細看,僅供參考

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爲隨之變化




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章