更好地解釋事情下面我已經把。這演示了修復子視圖佈局的兩種方法。在使用約束時,我更願意將約束作爲數組創建,並一次性激活它們,正如您將在createredSquareWithConstraints的代碼中看到的一樣。一個約束只是一個線性方程,將一個視圖的特徵與另一個視圖的特徵相關聯。例如,在「僞代碼」中,我的數組中的第一個約束可寫爲:
「將子視圖的前導邊距設置爲等於容器視圖的前導邊距的1倍加上常數0。
(這就是我爲什麼,因爲它看着我,彷彿你是基於它的子視圖的一個特點設置包含視圖的約束是越來越早混淆。)
雖然仍完全有效利用佈局約束條件,我認爲現在的首選方法是重寫viewWillTransitionToSize()委託方法,它只是簡單地要求您在給定包含視圖的大小的情況下指定視圖控制器子視圖的框架應該是什麼。因此,我也包含了一個實現,創建一個初始幀的黃色方塊,然後在調用viewWillTransitionToSize時進行修改。我個人覺得使用佈局約束要少得多。
如果你隨着按鈕放置並旋轉屏幕,你會發現任何一種方法都能達到同樣的效果。 [注:我已經將一個方格標記爲受限制,而另一個標記爲不受約束,但實際上它們當然都受到約束,只是以不同的方式。我會補充一點,這顯然不是你在實踐中將如何做的事情 - 你應該選擇一種方法並堅持下去,否則你的代碼將會遍佈全球!]。
希望有幫助!
import UIKit
class ViewController: UIViewController {
var constrainedredSquare : UIView!
var unconstrainedRedSquare : UIView!
var methodOneButton : UIButton!
var methodTwoButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor.blue
func getButton(name: String) -> UIButton {
let button : UIButton = UIButton()
button.backgroundColor = UIColor.white
button.layer.cornerRadius = 3
button.clipsToBounds = true
button.setTitle(name, for: UIControlState.normal)
button.setTitleColor(UIColor.black, for: UIControlState.normal)
return button
}
self.methodOneButton = getButton(name: "Red - Constraints")
self.methodTwoButton = getButton(name: "Yellow - viewWillTransitionToSize")
self.methodOneButton.addTarget(self, action: #selector(self.createRedSquareWithConstraints), for: .touchUpInside)
self.methodTwoButton.addTarget(self, action: #selector(self.createYellowSquareWithoutConstraints), for: .touchUpInside)
self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300))
self.methodTwoButton.frame = CGRect(origin: CGPoint(x: self.view.frame.width - 500, y: 100), size: CGSize(width: 300, height: 300))
self.view.addSubview(self.methodOneButton)
self.view.addSubview(self.methodTwoButton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: size)
}
self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300))
self.methodTwoButton.frame = CGRect(origin: CGPoint(x: size.width - 500, y: 100), size: CGSize(width: 300, height: 300))
}
func createYellowSquareWithoutConstraints() {
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.removeFromSuperview()
}
else
{
if let _ = constrainedredSquare {
self.constrainedredSquare.removeFromSuperview()
}
self.unconstrainedRedSquare = UIView()
self.unconstrainedRedSquare.backgroundColor = UIColor.yellow
self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: self.view.frame.size)
self.view.addSubview(self.unconstrainedRedSquare)
self.view.bringSubview(toFront: self.methodOneButton)
self.view.bringSubview(toFront: self.methodTwoButton)
}
}
func createRedSquareWithConstraints() {
if let _ = self.constrainedredSquare {
self.constrainedredSquare.removeFromSuperview()
}
else
{
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.removeFromSuperview()
}
let redSquare : UIView = UIView()
redSquare.backgroundColor = UIColor.red
self.view.addSubview(redSquare)
self.view.bringSubview(toFront: self.methodOneButton)
self.view.bringSubview(toFront: self.methodTwoButton)
let rsConstraints : [NSLayoutConstraint] = [NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.height, multiplier: 1.0, constant: 0)]
redSquare.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(rsConstraints)
}
}
}
這可能是一個愚蠢的問題/我可能無法正確讀取你的代碼,但是有你錯誤地解決了你的限制?您是否應該根據舊視圖的約束條件來設置新視圖的約束條件?它看起來好像你是基於新的子控制器的視圖爲父控制器的視圖設置約束。 – Sparky
@Sparky你的意思是這樣嗎? controller.view.topAnchor.constraint(equalTo:view.topAnchor).isActive = true。我這樣做,行爲是一樣的。 –
@Sparky?對不起,我對iOS開發比較陌生。律'的幫助?謝謝! –