iOS開發之有趣的UI —— 自定義不等高cell

這裏寫圖片描述

一、靜態cell和動態cell
一般比較固定的樣式可通過storyboard中的靜態cell或者動態cell進行操作,方便快捷高效。
靜態cell創建方式
動態cell創建方式

二、純代碼是實現自定義不等高cell
下面通過案例來實現用純代碼的方式來完成自定義不等高cell的實現。

項目需求:
以微博爲例,當別人髮狀態時,有的人發文字,有的人發文字和圖片,那麼如何實現這種方式呢?

項目思路:
在UITableViewCell中的系統樣式中不能滿足項目所需,那麼我們首先得想,通過自定義cell的方式來完成,至於高度不等,那麼我們可以在每一個cell中通過判斷哪個控件是最後一個,然後就取它的高度然後和cell底部間留有間距就完成了。

項目實現過程:
1.創建項目,導入圖片及plist文件
2.創建數據模型,用來進行plist字典數據轉模型
3.創建一個繼承自UITableViewCell的文件用來設置自定義cell以及數據的重寫
4.在控制器中遵守UITableViewDataSourse協議,創建代理對象,實現代理方法等。

項目代碼編碼過程:
1.創建項目,導入圖片及plist文件

2.創建ZJStatus數據模型
在ZJStatus.h中
/* 內容數據***********/
/* 頭像 /
@property (nonatomic ,copy)NSString *icon;
/* 暱稱 /
@property (nonatomic ,copy)NSString *name;
/* vip /
@property (nonatomic ,assign)BOOL vip;
/* 文字 /
@property (nonatomic ,copy)NSString *text;
/* 圖片 /
@property (nonatomic ,copy)NSString *picture;

在ZJStatus.m中不做任何操作

(3)創建ZJStatusCell文件用來設置自定cell以及重寫數據
在ZJStatusCell.h中
先導入@class ZJStatus;
將ZJStatus 所有屬性進行聲明
/* status的數據 /
@property (nonatomic,strong) ZJStatus *status;

在ZJStatusCell.m中

#import "ZJStatus.h"
#define KNameFont [UIFont systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()

// 聲明一些屬性
#import "ZJStatus.h"
#define KNameFont [UIFont 

// 定義宏 
systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]


@interface ZJStatusCell ()
/** 頭像 */
@property (nonatomic ,weak)UIImageView *iconImageView;
/** 暱稱 */
@property (nonatomic ,weak)UILabel *nameLabel;
/** vip */
@property (nonatomic ,weak)UIImageView * vipImageView;
/** 文字 */
@property (nonatomic ,weak)UILabel *TEXTLabel;
/** 圖片 */
@property (nonatomic ,weak)UIImageView *pictureImageView;

@end
@implementation ZJStatusCell
/**
 *  添加子控件(把有可能顯示的子控件都加進去)
 */
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        // 1.暱稱
        UIImageView *iconImageView = [[UIImageView alloc]init];
        [self.contentView addSubview:iconImageView];
        // 連線 建立關係
        self.iconImageView = iconImageView;

        // 2.標題
        UILabel *nameLabel = [[UILabel alloc]init];
        [self.contentView addSubview:nameLabel];
        self.nameLabel = nameLabel;
        // 設置文字大小
        self.nameLabel.font = KNameFont;
        // 連線 建立關係
        self.nameLabel = nameLabel;

        // 3.vip
        UIImageView *vipImageView = [[UIImageView alloc]init];
        vipImageView.image = [UIImage imageNamed:@"vip"];
        // 圖片顯示格式
        vipImageView.contentMode = UIViewContentModeCenter;
        [self.contentView addSubview:vipImageView];
        // 連線 建立關係
        self.vipImageView = vipImageView;

        // 4.文字
        UILabel *TEXTlabel = [[UILabel alloc]init];
        [self.contentView addSubview:TEXTlabel];
        self.TEXTLabel = TEXTlabel;
        // 設置文字大小
        self.TEXTLabel.font = KTextFont;
        // 連線 建立關係
        self.TEXTLabel = TEXTlabel;
        // 換行
        self.TEXTLabel.numberOfLines = 0;
        // 設置一個背景顏色
        self.TEXTLabel.backgroundColor = [UIColor redColor];

        // 5.配圖
        UIImageView *pictureImageView = [[UIImageView alloc]init];
        [self.contentView addSubview:pictureImageView];
        self.pictureImageView = pictureImageView;
        // 連線 建立關係
        self.pictureImageView = pictureImageView;
    }

    return self;
}

// 佈局子控件

- (void)layoutSubviews{
#warning 一定要調用 [super layoutSubviews];
    [super layoutSubviews];
    CGFloat margin = 10;
    // 1.設置頭像的位置
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconW = 40;
    CGFloat iconH = iconW;
    self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.設置標題位置
    CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
    CGFloat nameY = iconY;
    // 計算文字所佔據的尺寸
    NSDictionary *nameAttri = @{NSFontAttributeName :KNameFont
                               };
    CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
    // 包裝成結構體
    self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};

    // 3.設置vip圖標
    if (self.status.vip) {
     CGFloat vipX = CGRectGetMaxX(self.nameLabel.frame) + margin;
     CGFloat vipY = nameY;
     CGFloat vipW = 14;
     CGFloat vipH = nameSize.height;
    self.vipImageView.frame = CGRectMake(vipX, vipY, vipW, vipH);
    }
    // 4.文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(self.iconImageView.frame) + margin;
    CGFloat textW = self.contentView.frame.size.width - iconX * 2;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textSize = @{NSFontAttributeName:KTextFont
                               };


    CGFloat textH = [self.status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

    self.TEXTLabel.frame = CGRectMake(textX, textY, textW, textH);
    // 配圖
    if (self.status.picture) {
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(self.TEXTLabel.frame) +margin;
        CGFloat pictureW = 100;
        CGFloat pictureH = pictureW;
        self.pictureImageView.frame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
    }

}

- (void)setStatus:(ZJStatus *)status{
    _status = status;
    self.iconImageView.image = [UIImage imageNamed:status.icon];
    self.nameLabel.text = status.name;
    self.TEXTLabel.text = status.text;
    // 圖片
    if (status.picture) {
        self.pictureImageView.hidden = NO;
        self.pictureImageView.image = [UIImage imageNamed:status.picture];
    }
    else {
        self.pictureImageView.hidden = YES;

    }
    // vip 圖標
    if (status.vip) {
        self.vipImageView.hidden = NO;

        self.nameLabel.textColor = [UIColor orangeColor];
    }else{
        self.vipImageView.hidden = YES;
        self.nameLabel.textColor = [UIColor blackColor];
    }

}

在控制器中:

#import "ZJStatus.h"
#import "ZJStatusCell.h"
// 導入第三方數據轉模型框架MJExtension
#import "MJExtension.h"

@interface ViewController ()

/** status的數組 */
@property (nonatomic,strong) NSArray *statuses;
@end

@implementation ViewController

- (NSArray *)statuses{
    if (!_statuses) {
        _statuses = [ZJStatus objectArrayWithFilename:@"statuses.plist"];
    }
    return _statuses;

}

 NSString *ID = @"status";
- (void)viewDidLoad {
    [super viewDidLoad];
// 註冊
    [self.tableView registerClass:[ZJStatusCell class] forCellReuseIdentifier:ID];

 }
#pragma  mark - 數據源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.statuses.count;

}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    ZJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    cell.status = self.statuses[indexPath.row];
    return cell
    ;
}

#pragma mark - 通過代理方法來算高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 從模型中取出數據
    ZJStatus *status = self.statuses[indexPath.row];
    CGFloat margin = 10;
    CGFloat cellHeight = 0;

    // 1.設置頭像的位置
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconW = 40;
    CGFloat iconH = iconW;
   CGRect iconImageView = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
    CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
                               };

    CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

     CGRect TEXTLabel  = CGRectMake(textX, textY, textW, textH);

    // 配圖
    if (status.picture) {
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(TEXTLabel) +margin;
        CGFloat pictureW = 100;
        CGFloat pictureH = pictureW;
        CGRect pictureImageView  = CGRectMake(pictureX, pictureY, pictureW, pictureH);

 // 如果有圖片 cellHeight的Y就等於圖片的最大值
        cellHeight = CGRectGetMaxY(pictureImageView);
    }
    else {
// 如果沒有圖片 cellHeight的Y就等於文字邊距的最大值

        cellHeight = CGRectGetMaxY(TEXTLabel);

    }
    cellHeight += margin;

    return cellHeight;
}

這種完成自定義不等高cell方式很low在實現代理方法來算高度的時候又把ZJStatusView中的設置位置方式寫了一遍,這樣寫性能會有所下降,爲了提高性能,可採用MVVM設計模式進行實現,後面會單另做MVVC設計模式的分享 。

三、根據文字來創建自適應大小方式。

  // 自適應文字及高度顯示
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
// 設置文字的自適應寬度 ,屏幕的寬度減去兩邊的間距
    CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;

// 設置文字顯示的最大高度
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
// 字典包裝文字本身大小
    NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
                               };
//  算出文字的自適應高度
    CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

     CGRect TEXTLabel  = CGRectMake(textX, textY, textW, textH);


// 自適應文字寬度顯示
    CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
    CGFloat nameY = iconY;
 // 計算文字本身所佔據的尺寸
    NSDictionary *nameAttri = @{NSFontAttributeName :[UIFont systemFontOfSize:14.0]
                               };
    CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
    // 包裝成結構體
    self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章