UITableViewCell AutoLayout動態(tài)行高總結(jié)(兼容iOS7)

最近在工作中遇到了一個問題,就是在AutoLayout中如何使UITableViewCell的行高根據(jù)內(nèi)容(具體就是UILabel的多行顯示)達(dá)到自適應(yīng)高度榛丢。google so一通找到了一些資料,但都不是特別齊全宜岛,特別是針對iOS7的兼容上姜贡,因此也踩了不少坑,在這里做一個總結(jié)磷支。

首先看一下效果

動態(tài)行高.png

其實(shí)在iOS8以上谒撼,cell的動態(tài)高度的實(shí)現(xiàn)已經(jīng)變的很方便了,只需要你在cell里面正確設(shè)置約束雾狈,再設(shè)置tableview的幾個屬性廓潜,就大功告成了!

首先正確設(shè)置約束

設(shè)置約束.png

這里要注意的就是善榛,一定要確保在設(shè)置約束之前辩蛋,你UITableViewCell的size inspector里面 Row Height 是Default而不是custom的數(shù)值,否則之后不管你如何操作移盆,UITableViewCell優(yōu)先使用的都是custom的數(shù)值

行高為Default.png

還有一點(diǎn)要注意的是悼院,如果你和我一樣,是UILabel需要多行顯示造成的行高不固定咒循,那么你的UILabel的行數(shù)要設(shè)置為0据途,表示UILabel顯示的是多行。

Lines為0.png

最后在viewDidLoad中加上

self.tableView.estimatedRowHeight = 56
self.tableView.rowHeight = UITableViewAutomaticDimension

estimatedRowHeight是假定的高度叙甸,因?yàn)樾枰A(yù)估UITableViewUIScrollViewcontentSize颖医。因此這種方法可能潛在的問題就是數(shù)據(jù)量大的時候滾動條可能會閃動。具體的解決方法還沒有研究裆蒸,應(yīng)該可以通過UIScrollView的代理方法解決熔萧。UITableViewAutomaticDimension這一句在iOS8+是作為rowHeight的默認(rèn)值的,這句話也可以不寫僚祷。

至此iOS8+ AutoLayout的動態(tài)行高就大功告成了哪痰,你甚至可以不用去實(shí)現(xiàn)heightForRowAtIndexPath

但是iOS7的兼容就顯得蛋疼許多了久妆,主要是由于晌杰,iOS7使用UITableView一定要實(shí)現(xiàn)heightForRowAtIndexPath代理方法,這里你可能會覺得筷弦,那我們實(shí)現(xiàn)這個代理方法肋演,返回UITableViewAutomaticDimension就好了啊抑诸,遺憾的是UITableViewAutomaticDimension在iOS7里面也是不可用的,不信你可以試一下爹殊,直接crash嫩舟。

所以我們的思路得這樣走付呕,實(shí)現(xiàn)heightForRowAtIndexPath, 創(chuàng)建一個臨時的cell,設(shè)置cell里面各個view的屬性果覆,主動觸發(fā)layout,通過UIView的方法systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)獲取cell的實(shí)際尺寸衔瓮,作為返回的高度存捺。代碼看起來像下面這樣.

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        
        //兼容ios7
        if NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0 {
                let mockcell = tableView.dequeueReusableCellWithIdentifier(youtidentifier)
                //
                //設(shè)置你的cell的子view,比如UILabel的title
                //
                let height =  mockcell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
                return height
            }
        }
        else {
            return UITableViewAutomaticDimension
        }
    }

上面的代碼需要注意的一點(diǎn)就是铅碍,tableView.dequeueReusableCellWithIdentifier這個方法千萬不能傳入indexPath润绵,否則會死循環(huán),一直調(diào)用該方法胞谈。

上面的代碼其實(shí)還有一個很明顯的問題尘盼,就是每一次計(jì)算高度都需要創(chuàng)建一次UITableViewCell,我們可以做一個簡單的改進(jìn)烦绳,用一個Dictionary<NSIndexPath,CGFloat>存儲計(jì)算過的indexPath對應(yīng)的height卿捎,代碼如下。

private var heightOfIndex = [NSIndexPath:CGFloat]()
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        
        //兼容ios7
        if NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0 {
            if let height = self.heightOfIndex[indexPath] {
                return height
            } else {
                let mockcell = tableView.dequeueReusableCellWithIdentifier(youtidentifier)
                //
                //設(shè)置你的cell的子view径密,比如UILabel的title
                //
                let height =  mockcell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
                self.heightOfIndex[indexPath] = height
                return height
            }
        }
        else {
            return UITableViewAutomaticDimension
        }
    }

為了能夠代碼重用娇澎,我們可以把他封裝成一個類,設(shè)置cell的過程作為一個block傳入睹晒。

class ALTableViewCellHeight {
    
    private var heightOfIndex = [NSIndexPath:CGFloat]()
    
    func heightForRowAtIndexPath(indexPath:NSIndexPath,initCell:()->UITableViewCell) -> CGFloat {
        if NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0 {
            if let height = self.heightOfIndex[indexPath] {
                return height
            } else {
                let cell = initCell()
                cell.layoutIfNeeded()
                let height =  cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
                self.heightOfIndex[indexPath] = height
                return height
            }
        }
        else {
            return UITableViewAutomaticDimension
        }
    }
}

最后再說說iOS7下UILabel的一個坑趟庄,如果要使你的UILabel能夠正常的多行顯示,除了一開始說到的設(shè)置numberOfLines為0伪很,還需要設(shè)置preferredMaxLayoutWidth戚啥,這個屬性指的當(dāng)換行的最大寬度。iOS8+能夠通過AutoLayout計(jì)算出UILabel的寬度锉试,把這個寬度作為preferredMaxLayoutWidth猫十,但是iOS7下面不行,應(yīng)該是一個bug呆盖。解決的方案是繼承UILabel拖云,重寫layoutSubviews

class LabelDynamicHeight:UILabel {
    override func layoutSubviews() {
        super.layoutSubviews()
        self.preferredMaxLayoutWidth = self.frame.size.width
        super.layoutSubviews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.numberOfLines = 0
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末应又,一起剝皮案震驚了整個濱河市宙项,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌株扛,老刑警劉巖尤筐,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汇荐,死亡現(xiàn)場離奇詭異,居然都是意外死亡盆繁,警方通過查閱死者的電腦和手機(jī)掀淘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來油昂,“玉大人革娄,你說我怎么就攤上這事∶岬” “怎么了拦惋?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸣哀。 經(jīng)常有香客問我架忌,道長吞彤,這世上最難降的妖魔是什么我衬? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮饰恕,結(jié)果婚禮上挠羔,老公的妹妹穿的比我還像新娘。我一直安慰自己埋嵌,他們只是感情好破加,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雹嗦,像睡著了一般范舀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上了罪,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天锭环,我揣著相機(jī)與錄音,去河邊找鬼泊藕。 笑死辅辩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娃圆。 我是一名探鬼主播玫锋,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讼呢!你這毒婦竟也來了撩鹿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤悦屏,失蹤者是張志新(化名)和其女友劉穎三痰,沒想到半個月后吧寺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡散劫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年稚机,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片获搏。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡赖条,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出常熙,到底是詐尸還是另有隱情纬乍,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布裸卫,位于F島的核電站仿贬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏墓贿。R本人自食惡果不足惜茧泪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望聋袋。 院中可真熱鬧队伟,春花似錦、人聲如沸幽勒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啥容。三九已至锈颗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咪惠,已是汗流浹背击吱。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硝逢,地道東北人姨拥。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像渠鸽,于是被迫代替她去往敵國和親叫乌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

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