升級(jí)到 iOS 11 之后混滔,tableView變化很大据途,此篇主要說明 section 的 headerView 根據(jù)設(shè)置的約束自動(dòng)適配行高的問題欣孤。
內(nèi)容提要
- 升級(jí)到 iOS 11 之后嫉沽,使用 tableView 封裝的仿QQ好友二級(jí)列表控件點(diǎn)擊組頭視圖 headerView 時(shí)會(huì)報(bào)很多約束錯(cuò)誤择诈,并且 contentView 的高度為0 械蹋!
- 預(yù)估行高 estimatedHeaderHeight 的問題。
原來是使用 masonry 自動(dòng)布局羞芍,跟 cell 的自動(dòng)行高一樣哗戈,系統(tǒng)自動(dòng)適配組頭 view 的行高。
問題描述
問題一:
實(shí)際問題是這樣的涩金,section 的 headerFooterView 中有上下排列的兩個(gè)Label谱醇,暫且這樣叫法:上面的 Label 是 lblName; 下面的 Label 是 lblAddr 暇仲,由于地址 addr 的字?jǐn)?shù)不確定,所以可能需要多行顯示副渴,相應(yīng)地 headerView 的高度也要自動(dòng)跟隨變化奈附。
之前是使用類似 cell 自動(dòng)行高那種傳統(tǒng)的設(shè)置方式,
tableView.estimatedSectionHeaderHeight = 50;
tableViwe.rowHeight = UITableViewAutomaticDimension;
然后垂直方向約束設(shè)置 --
lblName 的約束 【make.top.equalTo(self.contentView).mas_offset(5);】
lblAddr 的約束 【make.bottom.equalTo(self.contentView).mas_offset(-5);】
但是發(fā)現(xiàn)點(diǎn)擊顯示子列表cell的時(shí)候會(huì)有 headerView 的約束錯(cuò)誤煮剧,錯(cuò)誤的意思就是說contentView的高度為 0 并且重復(fù)設(shè)置了高度之類(具體錯(cuò)誤內(nèi)容不在此描述斥滤,此處只討自動(dòng)行高論解決方案~)
經(jīng)過試驗(yàn),如果設(shè)置 lblName.top 距離 contentView.top 為 0勉盅,lblAddr.bottom 距離 contentView.bottom 的距離為 0佑颇,是沒有問題的,不管怎么點(diǎn)擊時(shí)不報(bào)約束錯(cuò)誤的草娜。
于是有了這樣一種解決方案挑胸,那就是,如果想讓 lblName.top 距離 contentView.top 是 x宰闰,就在此填充一個(gè)高度為 x 的 view茬贵;
同理,lblAddr.bottom 到 contentView.bottom 之間也填充一個(gè)高度為 y 的小 view移袍。
這樣自上而下全部填充滿 contentView 而不是留空解藻,就不會(huì)出現(xiàn)之前的約束錯(cuò)誤!
同樣地葡盗,水平方向也是如此設(shè)置螟左,使用寬度固定的小view填充。
當(dāng)然觅够,如果 contentView 內(nèi)部的控件距離 contentView 的邊緣為0的話胶背,就不必使用小view填充了,直接設(shè)置邊緣距離為0就可以了喘先。
目前只發(fā)現(xiàn)這種方法奄妨,可能比較笨拙。希望找到更好的辦法苹祟,還望路過的大神不吝賜教,同時(shí)希望朋友們相互討論共同進(jìn)步评雌。
問題二:
如上使用小view填充的方式設(shè)置好了树枫,那么是不是就一切 OK 了呢?
當(dāng)然不是景东,這里面還發(fā)現(xiàn)一個(gè)坑砂轻。
我們知道 iOS 11 之后,tableView 默認(rèn)使用了 Self-Sizing estimatedSectionHeaderHeight = 44斤吐。這個(gè)屬性是預(yù)估 header 行高搔涝,也可以通過相同名稱的代理來返回預(yù)估 header 行高厨喂。tableView 會(huì)現(xiàn)根據(jù)預(yù)估行高計(jì)算出總高度,然后再慢慢計(jì)算實(shí)際高度庄呈。這些點(diǎn)詳細(xì)資料很多蜕煌,大家自己谷歌就可以,此處不再贅述诬留。
在 iOS 11 之前斜纪,我們給個(gè)預(yù)估行高(不管是 sectionHeader 還是 cell 的預(yù)估行高)并設(shè)置 headerView.rowHeight = UITableViewAutomaticDimension;然后在內(nèi)部 contentView 中設(shè)置好連貫的約束文兑,就可以實(shí)現(xiàn)自動(dòng)適配行高盒刚。注意:不管這個(gè)預(yù)估行高是大于真實(shí)的行高還是小于真實(shí)的行高,都沒有問題绿贞。
但是同樣的項(xiàng)目在 iOS 11 之后發(fā)現(xiàn)因块,當(dāng)內(nèi)容很多需要增加高度顯示的時(shí)候就會(huì)報(bào)約束錯(cuò)誤!經(jīng)過對(duì)比發(fā)現(xiàn)籍铁,當(dāng)真實(shí)行高大于預(yù)估行高時(shí)就會(huì)報(bào)約束錯(cuò)誤涡上,反之則沒有問題!
所以是這樣解決的寨辩,在返回真實(shí)行高的代理方法中
【 return UITableViewAutomaticDimension; 】吓懈,
在返回預(yù)估行高中,盡量返回一個(gè)比“預(yù)期”的行高大一點(diǎn)的值靡狞,這樣就沒問題了耻警。
解決方案
問題一,使用小 view 填充 margin甸怕。
問題二甘穿,返回的預(yù)估行高盡量大,比“預(yù)期”的行高大一點(diǎn)梢杭。
由此温兼,上面兩個(gè)問題都得到解決。
這是目前項(xiàng)目中遇到的坑武契,寫出來與大家分享討論募判,希望能有更好的解決方案。
附:
升級(jí)到 iOS 11 之后咒唆,tableView上方會(huì)留有一行空白届垫,通過設(shè)置contentOffset和tableView.headerView = [[UIView alloc] init]; 的方式設(shè)置都去不掉。后來設(shè)置headerView的高度為0.1全释,就可以解決装处。
self.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 0.1)];
self.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 0.1)];
------------------ 分割線 ------------------
2017-12-28
補(bǔ)充:
對(duì)于前面所說的“margin 需要使用小 view 代替填充”的問題,在最近設(shè)置自動(dòng)cell的行高時(shí)浸船,又有了新的變化妄迁。
現(xiàn)在不必使用小view 填充了寝蹈,還是使用
【make.top.equalTo(self.view).mas_offset(8); 】
這樣子來設(shè)置就ok了,真是奇怪登淘!