熟練使用Autolayout就要熟悉各種場景和控件,一段時間不用就手生;
NSLayoutConstraint這個屬性用于動態配置ScrollView中,有了他適配ScrollView時結合代碼就非常方便了。
@IBOutlet weak var viewHight: NSLayoutConstraint!
在加載方法里動態更新高度
override func viewDidLoad() {
super.viewDidLoad()
let dyHight = infoHeight + CGFloat(logStr.components(separatedBy: "\n").count * 12)
viewHight.constant = dyHight
self.infoView.setNeedsLayout()//更新視圖
}
不過這種修改辦法有時可能失效,原因是:你在 viewDidLoad中修改的約束的代碼塊運行了,但是 運行完之后 又被 storyboard自己的配置給覆蓋了,所以 你看到的還是你之前設置的約束!大概是XIB文件讀取的比較耗時的原因吧!xib耗時少一些。解決辦法是:讓修改 constant值或者約束的語句延遲執行即可!即使是 0.1秒,也能讓 在storyboard初始完成之后你再修改相應的約束,這樣就不會被覆蓋掉了!解決辦法:
[self performSelector:@selector(修改constant) withObject:nil afterDelay:0.1];//延遲加載,執行
了解視圖的加載、渲染、展示周期(UIView的生命周期總結)可以幫助你理解上面的這段話:
UIKit極大的簡化了加載和展示View的過程,它大概會按照以下順序執行一些任務:
1. 通過storyboard文件中的信息實例化視圖
2. 連接outlet和action
3. 把根視圖賦值給UIViewController的view屬性(其實就是調用loadView 方法)
4. 調用UIViewController的awakeFromNib方法。要注意,在調用方法前,的trait collecion為空且子視圖的位置可能不正確
5. 調用UIViewController的viewDidLoad方法。
此時已經完成了視圖的加載工作,在展示到屏幕之前,還有以下幾個步驟:
1. 調用UIViewController的viewWillAppear方法。
2. 更新視圖的布局
3. 把視圖展示到屏幕上
4. 調用UIViewController的viewDidAppear方法
視圖的生命歷程
到目前為止,我們已經了解了每個方法的作用,接下來就把整個流程梳理一遍。
1. -[ViewController initWithCoder:]或-[ViewController initWithNibName:Bundle]:首先從歸檔文件中加載UIViewController對象。即使是純代碼,也會把nil作為參數傳給后者。
2. -[UIView awakeFromNib]:作為第一個方法的助手,方便處理一些額外的設置。
3. -[ViewController loadView]:創建或加載一個view并把它賦值給UIViewController的view屬性
4. -[ViewController viewDidLoad]:此時整個視圖層次(view hierarchy)已經被放到內存中,可以移除一些視圖,修改約束,加載數據等
5. -[ViewController viewWillAppear:]:視圖加載完成,并即將顯示在屏幕上,還沒有設置動畫,可以改變當前屏幕方向或狀態欄的風格等。
6. -[ViewController viewWillLayoutSubviews]:即將開始子視圖位置布局
7. -[ViewController viewDidLayoutSubviews]:用于通知視圖的位置布局已經完成
8. -[ViewController viewDidAppear:]:視圖已經展示在屏幕上,可以對視圖做一些關于展示效果方面的修改。
9. -[ViewController viewWillDisappear:]:視圖即將消失
10. -[ViewController viewDidDisappear:]:視圖已經消失
如果考慮UIViewController可能在某個時刻釋放整個view。那么再次加載視圖時顯然會從步驟3開始。因為此時的UIViewController對象依然存在。
以上這個方法是修改約束最簡單辦法了,不過還有以下幾種有興趣的話互相交流
目前我已知的方法有5種
1.修改frame(有時候可能會不起作用,但可以做動畫)
2.修改約束的float值
3.使用VisualFormat 語言
4.使用 constraintWithItem,按倍率改變 如 2x+1=Y
5.移除約束(remove at runtime),添加新的約束
以上只是原理,具體操作才是最重要的:
左右間距分別是28,這樣保證了寬度,寬高等比保證了高度,也保證了圖片不會壓縮變形,center.x和center.y保證了在屏幕中的位置,整體保證了AlertView的frame所以約束不會出錯(除此之外有很多種方式保證frame)。無論是用哪種方式布局約束,最終目的是保證frame是固定的就算合理約束。
另外幾個控件也要求等比,通過conter.y確定位置,以保證顯示在背景圖片的合適位置上
如果這個Lable上的字很多的話有兩種方式可以避免出現文字顯示不全,視情況選擇:
第一種方法文字自動變小,第二種方法label變長
底部的兩個按鈕靠底居中約束并且按比例縮放圖片:
又一次說明無論是以什么樣的方式只要保證視圖的Frame是固定的就能保證約束沒有問題,無論你是通過邊界值固定,還是通過center都沒有關系。
動態設置scrollview的高度就用到了前面提到的“修改constant”,不過約束的時候要保證子視圖固定的高度,以確保scrollview的Frame是固定的。
這就確保了在執行loadView之前nib文件中的信息的完整性,添加完屬性后會在viewDidLoad中修改constant的值,然后在viewWillLayoutSubviews中對視圖重新布局
代碼動態更改約束,在viewDidLoad中調用:
func initSubviews(){
self.infoLabel.text = ""
viewHight.constant = 420//這里可以根據自己的業務邏輯動態計算
self.infoView.setNeedsLayout()//更新視圖
var labelR:CGRect = self.infoLabel.frame
labelR.size.height = 420
self.infoLabel.frame = labelR
}
)
大功告成,歡迎交流歡迎指導共同進步!
Demo自取
如果對你有幫助,歡迎給個Star