仿簡友動態時間軸:使用Snapkit來實現UITableViewCell的動態布局

jopen 8年前發布 | 38K 次閱讀 iOS開發 移動開發

效果展示:


簡書
</div>

思路:

前陣子做簡書首頁的時候需要的坑主要是ScrollViewAutoLayout的問題,當時的解決方式是:Scrollview里面放一個ContainView,然后子視圖拉約束到ContainView,這樣ContainView的大小就可以根據子視圖來變化,Scrollview的大小根據ContainView來定。

有兩個特別需要注意點:
1.scrollView內部子控件的尺寸不能以scrollView的尺寸為參照
2.scrollView內部的子控件的約束必須完整(子控件在水平和垂直方向用約束把ContainView撐滿,使containtView擴展以適合它們的尺寸。例如:以前普通布局,只需要定義寬高、左、上的距離即可,但是這時候需要把下、右的距離也補上,不然containView不知道到底尺寸多大)


Cell分析
</div>


這里動態UITableViewCell的思路與上面類似,我們需要讓Cell的子控件把約束固定到ContentView上,而且要約束完整。但是簡友動態還有一個問題就是高度可變(子View有時候需要隱藏),采取的解決方案是:對約束增加優先級的差異,對單條Constraint進行activedeactive操作,那么意味著可以動態的啟用或者禁用某條預置的約束。所以我們只要預先設置一條高優先級的高度為0(或者寬度為0)的約束 然后在適當的時候激活它就可以了。

代碼演練:

為了代碼簡介只寫重點部分

    sourceUserLabel = UILabel()
    sourceUserLabel.sizeToFit()
    contentView.addSubview(sourceUserLabel)
    sourceUserLabel.snp_makeConstraints { (make) -> Void in

    make.top.equalTo(contentView).offset(30)
    make.left.equalTo(contentView).offset(20)

}

eventLabel = UILabel()
eventLabel.sizeToFit()
contentView.addSubview(eventLabel)
eventLabel.snp_makeConstraints { (make) -> Void in
    make.left.equalTo(sourceUserLabel)
    make.top.equalTo(sourceUserLabel.snp_bottom).offset(10)
}</pre> 

這段代碼只是設置了用戶名和event類型(發布文字、喜歡之類) ,可以看出來只是設置了左、上的距離,以及SizeToFit,也就是設置了高度和寬度,但是并沒有把ContentView撐滿,繼續

    containView = UIView()
    containView.backgroundColor = UIColor.redColor()
    contentView.addSubview(containView)
    containView.snp_makeConstraints { (make) -> Void in
        make.top.equalTo(eventLabel.snp_bottom).offset(10)
        make.left.equalTo(contentView).offset(10)
        make.right.equalTo(contentView).offset(-20)

    }

    contentLabel = UILabel()
    contentLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
    contentLabel.font = UIFont.systemFontOfSize(18)
    contentLabel.numberOfLines = 3
    contentLabel.sizeToFit()
    containView.addSubview(contentLabel)
    contentLabel.snp_makeConstraints { (make) -> Void in
        make.edges.equalTo(containView).inset(UIEdgeInsetsMake(10, 10, 10, 10)).priorityHigh()
    }

這個是要把評論內容的Label放到了一個superView中,也就是ContainView中,然后ContainView的尺寸根據內部Label的尺寸來變化,所以Label約束也要滿足“撐滿”ContainView。make.edges.equalTo(containView).inset(UIEdgeInsetsMake(10, 10, 10, 10)).priorityHigh()SizetoFit結合就可以約束完整,確定ContainView的尺寸。注意PriorityHigh是設置約束優先級為750,默認為1000。

        containView.snp_makeConstraints { (make) -> Void in
        self.heightContraint = make.height.equalTo(0).constraint
        make.bottom.equalTo(contentView).offset(-10)
        self.heightContraint?.deactivate()
    }

這段代碼有關鍵作用,make.bottom.equalTo(contentView).offset(-10)來達到約束完整的目的,“撐滿”ContentView來確定具體尺寸。同時設置了 self.heightContraint = make.height.equalTo(0).constraint來使containView的告訴為0,約束優先級為1000.那么就是說當此約束activate()的時候,containView高度為零,隱藏。當deactivate()的時候,會使用優先級為750的約束來確定ContainView的高度。

    func cellType(bool: Bool){

    if bool{
        self.heightContraint?.activate()
    }
    else{
        self.heightContraint?.deactivate()
    }

}

注:

這個Demo的思路,已經運用到自己的開源項目“仿簡書Github”中,需要的小伙伴可以去下載一起來運行看一下效果。
ScrollViewAutoLayout的闡述放在Here
查閱資料的過程中,也接觸了壓縮阻力(compression resistance)和吸附性約束(hugging constraints)這樣的專業名詞,但是感覺“撐滿”、“完整”這樣的詞語更容易理解所以沒有提及這些名詞,如有不妥,請指正。

有愛的Swift交流群:331527020
希望小手能順便點一下??Star ^_^,朋友的鼓勵和支持是我們繼續分享的動力

來自: http://www.jianshu.com/p/3429ac5a4e4d

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!