UITableView-FDTemplateLayoutCell + 自動(dòng)布局讓 Cell 高度自適應(yīng)

前提

  • 本文以Swift 作為講解,OC 類似,不作贅述
  • 我們這里討論的是純代碼方式的布局,所以XIBStoryboard 的使用方式不在本文的討論范疇。

問(wèn)題描述

通常情況下,我們都是通過(guò)

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 50
}

提前告知每個(gè)Cell的高度。

當(dāng) UITableViewCell 中的內(nèi)容出現(xiàn)圖文混排時(shí),每個(gè)的Cell高度不盡相同。比較笨的做法,是使用 String 的自動(dòng)計(jì)算文本的高度(實(shí)際上是寬高都計(jì)算了,也就是size)

下面是根據(jù)字體大小計(jì)算系統(tǒng)默認(rèn)字體的 字符串 所占的寬度

// MARK: 計(jì)算字符鎖占的寬度
func calculateStringWidth(sourceString: String?, fontSize: CGFloat) -> CGFloat {
    guard let _ = sourceString else {
        return 0
    }

    let size: CGSize = CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT))
    let rect: CGRect = sourceString!.boundingRect(with: size, options: NSStringDrawingOptions.usesFontLeading, attributes: [kCTFontAttributeName as NSAttributedStringKey: UIFont.systemFont(ofSize: fontSize)], context: nil);
    return rect.width
}

事實(shí)上,就圖文混排的UITableViewCell 而言,特別需要高度的自適應(yīng)。

解決的第三方庫(kù)

使用的第三方庫(kù) UITableView-FDTemplateLayoutCell

解決思路

這里的思路是利用 autoLayout(實(shí)際上就是OC中的Masonry,Swift中的SnapKit) 寫好約束布局,在tableViewDelegate的高度和cell實(shí)現(xiàn)中作充數(shù)據(jù)填充(我這里叫render渲染),自動(dòng)把高度撐開的過(guò)程。


實(shí)例代碼:

TableView 中的代理

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return tableView.fd_heightForCell(withIdentifier: titleWithRightImageCellID, configuration: { (cell) in
            let currentCell = cell as! ArticleTitlWithRightImageCell
            currentCell.renderCell(with: self.testDataSource[indexPath.row])
        })
        
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        cell = (tableView.dequeueReusableCell(withIdentifier: titleWithRightImageCellID,
                                                  for: indexPath)) as! ArticleTitlWithRightImageCell
        cell.renderCell(with: testDataSource[indexPath.row])
        return cell
    }

可以看到,在兩個(gè)代理中調(diào)用了同一個(gè)渲染。渲染的實(shí)質(zhì)是讓其中的UILabelUIImage之類的數(shù)據(jù)重賦值。涉及之前有提到過(guò)的復(fù)用機(jī)制,這了不贅述。除此之外,渲染還做了一些約束的重置,因?yàn)橐恍┣闆r下,cell model 對(duì)應(yīng)的那個(gè)數(shù)據(jù)并不存在,需要隱藏

另外,實(shí)際上 UITableView-FDTemplateLayoutCellfd_heightForCell 中提供的方法不只是 fd_heightForCell一種,還有其他帶緩存的方法,因?yàn)闆](méi)有深入研究,這里不做展開了。

Cell 中的約束示例

private func setupConstrains() {
    titleLabel.snp.makeConstraints { (make) in
        make.top.equalTo(contentView.snp.top).offset(16).priority(.high)
        make.leading.equalTo(11)
        make.trailing.equalTo(-11)
    }
    
    imageViewContainer.snp.makeConstraints { (make) in
        make.left.right.equalTo(contentView)
        make.top.equalTo(contentLabel.snp.bottom).offset(10)
        make.height.equalTo(imageHeight)
    }
    
    footerView.snp.makeConstraints { (make) in
        make.height.equalTo(46)
        make.left.right.equalTo(contentView)
        make.bottom.equalTo(contentView.snp.bottom).priority(.high)
        make.top.equalTo(imageViewContainer.snp.bottom)
    }
}

約束中,務(wù)必注意以下幾點(diǎn),否則約束一旦出錯(cuò),就有可能無(wú)法撐開高度。

  • Cell需要使用tableViewregisterNib或者registerClass的方法進(jìn)行注冊(cè),否則會(huì)報(bào)異常。
  • 添加控件必須使用 self.contentView.addSubView
    • 所有的控件,必須添加到cell.contentView中去!
    • 所有的控件,約束也必須依賴于cell.contentView 而非 cell,否則會(huì)出錯(cuò)
  • 頂部和底部的約束必須寫好
    • 最上面的控件,要寫針對(duì)contentView.snp.top 的依賴,并設(shè)置最高權(quán)限 priority(.high)
    • 最下面的控件,要寫針對(duì)contentView.snp.bottom 的依賴,并設(shè)置最高權(quán)限 priority(.high)

如果不添加最高權(quán)限,你會(huì)發(fā)現(xiàn),我們的布局其實(shí)是正確的,但是一直會(huì)報(bào)一個(gè)類似 <NSLayoutConstraint UITableViewCellContentView.height == 44> 的約束沖突。實(shí)際測(cè)試發(fā)現(xiàn),是因?yàn)?heightForCell 默認(rèn)是一個(gè)44高度,我們?cè)诨卣{(diào)中使用了約束渲染把他撐開,他還是會(huì)報(bào)錯(cuò)

解決方案就是在頂部和底部添加最高約束權(quán)限。github issues 參考鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,228評(píng)論 3 119
  • 寒見的出現(xiàn),讓皇上如此這般意亂情迷,多少網(wǎng)友加我自己也覺(jué)心涼。曾經(jīng)少年,只那句“有我在,你放心”讓如懿癡了半生...
    宋大牙閱讀 200評(píng)論 0 0
  • Promise 是什么 Promise 是一種規(guī)范,在es6以前,瀏覽器沒(méi)有內(nèi)置的promise,不同框架有各自的...
    kokokokokoishi閱讀 2,387評(píng)論 1 3
  • 《一歲一生長(zhǎng)》 天堂去往人間的路上 泉水叮咚叮咚響 有光的地方滋生出一朵小紅花 咿呀咿呀,話語(yǔ)不詳 你猜,我想 人...
    小花朵的遠(yuǎn)方閱讀 380評(píng)論 1 6
  • 新高三的詩(shī)冰小妹,發(fā)給我兩道很有代表性的題目,在此給大家講解一下 這兩道題都是關(guān)于移動(dòng)支付與流通中的貨幣量的問(wèn)題,...
    兔兔俠的逆襲閱讀 16,403評(píng)論 0 1

友情鏈接更多精彩內(nèi)容