UITableViewCell高度自適應(yīng)探索--AutoLayout結(jié)合Frame

之前我們已經(jīng)對(duì)Cell高度自適應(yīng)進(jìn)行了幾次研究:
UITableViewCell高度自適應(yīng)探索--UITableView+FDTemplateLayoutCell
地址: http://www.reibang.com/p/7839e3a273a6
UITableViewCell高度自適應(yīng)探索--cell預(yù)估高度(一)
地址: http://www.reibang.com/p/6ab92579fcf1
UITableViewCell高度自適應(yīng)探索--cell預(yù)估高度(二)
地址: http://www.reibang.com/p/f3609cd9392e
今天,再提供一種AutoLayout與Frame相結(jié)合的方式來設(shè)置cell高度的方法.

今天這個(gè)方法的要點(diǎn)是:

  • 使用Autolayout在進(jìn)行布局.
  • 使用Frame進(jìn)行高度計(jì)算
  • 使用模型的屬性緩存每個(gè)Cell第一次計(jì)算的高度.

相對(duì)于之前說的那些方法,這個(gè)方法比UITableView+FDTemplateLayoutCell使用起來更簡(jiǎn)單和容易理解(自從寫FD那篇文章發(fā)表后收到很多網(wǎng)友的關(guān)于使用的問題,大部分是由于沒有使用正確);并且克服了預(yù)估高度方式的那些問題,也不用把約束改來改去, 使計(jì)算的過程更加可控.

這種方法雖然是使用fram的方式計(jì)算,但是如果沒有autoLayout,計(jì)算的過程就會(huì)復(fù)雜幾倍,有時(shí)候可能還需要一個(gè)專門的類去管理子控件的frame.在我看來是一個(gè)比較不錯(cuò)的方法.

進(jìn)入正題.

先看要實(shí)現(xiàn)的效果:

目標(biāo)效果

其中文字的長(zhǎng)度不一,圖片可能有或沒有.為了排除其他干擾,數(shù)據(jù)來自plist文件.

  • 這是我們自定義cell的設(shè)置,這些元素是固定的,我們使用AutoLayout對(duì)它們幾個(gè)進(jìn)行布局.
cell布局
  • 創(chuàng)建一個(gè)Message模型,賦予其對(duì)應(yīng)的屬性.
    由于cell的高度本質(zhì)上還是基于模型數(shù)據(jù)來算的,所以計(jì)算高度的任務(wù)交給模型,故模型同時(shí)開放一個(gè)cellHeight的只讀屬性,將來好拿給控制器使用.
@interface Message : NSObject

// 頭像、名字、和描述文字我給固定了,所以沒有弄屬性處理
@property (nonatomic, copy) NSString *imageName;
@property (nonatomic, copy) NSString *content;
@property (nonatomic, assign, readonly) CGFloat cellHeight;

@end
  • 模型計(jì)算Cell高度,通過重寫cellHeight的getter方法實(shí)現(xiàn)
- (CGFloat)cellHeight {
    if (!_cellHeight) {
        CGFloat contentW = [UIScreen mainScreen].bounds.size.width - 2 * margin; // 屏幕寬度減去左右間距
        CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT)
                                                      options:NSStringDrawingUsesLineFragmentOrigin
                                                   attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]}
                                                      context:nil].size.height;
        _cellHeight = contentLabelY + contentH + margin;
    }
    return _cellHeight;
}
注意:
上面高度的計(jì)算還沒有將內(nèi)容圖片的高度計(jì)算在內(nèi).
并且實(shí)現(xiàn)了利用模型的cellHeight屬性緩存第一次計(jì)算高度.
  • 由于內(nèi)容圖片不是每個(gè)cell都有,所以使用代碼動(dòng)態(tài)添加.
// 屬性聲明
@property (strong, nonatomic) UIImageView *contentImageView;
// getter實(shí)現(xiàn)
- (UIImageView *)contentImageView {
    if (!_contentImageView) {
        _contentImageView = [[UIImageView alloc] init];
        [self.contentView addSubview:_contentImageView];
    }
    return _contentImageView;
}
  • cell該接收模型了
@property (nonatomic, strong) Message *message;
- (void)setMessage:(Message *)message {
    _message = message;
    self.contentLabel.text = _message.content;
    if (message.imageName.length) {
        self.contentImageView.hidden = NO;
        self.contentImageView.image = [UIImage imageNamed:message.imageName];
    }
    else {
        self.contentImageView.hidden = YES;
    }
}

當(dāng)然,這時(shí)候contentImageView當(dāng)然是顯示不出來的,因?yàn)槲覀冞€沒有贈(zèng)送它一個(gè)frame.那么它的frame從何而來呢?

一開始我們說過,計(jì)算要基于模型,所以接下來的思路是由模型算出imageView的frame,拿去給cell用.

回到模型cellHeight的getter方法,添加對(duì)imageName屬性的處理:

// 圖片將要展示的frame作為模型的其中一個(gè)屬性
@property (nonatomic, assign) CGRect contentImageFrame;
- (CGFloat)cellHeight {
    if (!_cellHeight) {
        CGFloat contentW = [UIScreen mainScreen].bounds.size.width - 2 * margin; // 屏幕寬度減去左右間距
        CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT)
                                                      options:NSStringDrawingUsesLineFragmentOrigin
                                                   attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]}
                                                      context:nil].size.height;
        _cellHeight = contentLabelY + contentH + margin;

        // 對(duì)imageName屬性的處理
        if (self.imageName.length) {
            UIImage *image = [UIImage imageNamed:self.imageName];
            CGFloat imageH = image.size.height;
            CGFloat imageW = image.size.width;
            // 直接得出contentImageView應(yīng)該顯示的frame
            _contentImageFrame = CGRectMake(margin, _cellHeight, imageW, imageH);
            _cellHeight += imageH + margin;
        }
    }
    return _cellHeight;
}

當(dāng)上面代碼執(zhí)行完畢,contentImageFrame就有值了.接著,回到cell的setMessage:方法給contentImageView賦值.

- (void)setMessage:(Message *)message {
    _message = message;
    self.contentLabel.text = _message.content;
    if (message.imageName.length) {
        self.contentImageView.hidden = NO;
        self.contentImageView.image = [UIImage imageNamed:message.imageName];
        // 給圖片的frame賦值,這個(gè)值就是上面得到那個(gè)
        self.contentImageView.frame = _message.contentImageFrame;
    }
    else {
        self.contentImageView.hidden = YES;
    }
}
  • 這時(shí)候使用起來就非常輕松了
// 控制器tableView協(xié)議方法實(shí)現(xiàn)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    Message *message = self.dataList[indexPath.row];
    return message.cellHeight;
}

完整代碼下載:https://github.com/CoderAO/AutoCellHeightMix

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蕊温,一起剝皮案震驚了整個(gè)濱河市搬设,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌排拷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異倔幼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)爽待,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門损同,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸟款,你說我怎么就攤上這事膏燃。” “怎么了何什?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵组哩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)禁炒,這世上最難降的妖魔是什么而咆? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮幕袱,結(jié)果婚禮上暴备,老公的妹妹穿的比我還像新娘。我一直安慰自己们豌,他們只是感情好涯捻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著望迎,像睡著了一般障癌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辩尊,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天涛浙,我揣著相機(jī)與錄音,去河邊找鬼摄欲。 笑死轿亮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胸墙。 我是一名探鬼主播我注,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼迟隅!你這毒婦竟也來了但骨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤智袭,失蹤者是張志新(化名)和其女友劉穎奔缠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體补履,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡添坊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箫锤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贬蛙。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谚攒,靈堂內(nèi)的尸體忽然破棺而出阳准,到底是詐尸還是另有隱情,我是刑警寧澤馏臭,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布野蝇,位于F島的核電站讼稚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绕沈。R本人自食惡果不足惜锐想,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乍狐。 院中可真熱鬧赠摇,春花似錦、人聲如沸浅蚪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惜傲。三九已至洽故,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盗誊,已是汗流浹背时甚。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哈踱,地道東北人撞秋。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嚣鄙,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子串结,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容