典型的,加入一個子視圖的作法就是建立實例,指定位置,而後把它加入到視圖裏面來。在指定位置的代碼處,通常就是設置frame屬性便可,就像這樣:javascript
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = Page()
self.window?.makeKeyAndVisible()
return true
}
}
class Page: UIViewController{
var vw : UIView!
override func viewDidLoad() {
super.viewDidLoad()
vw = UIView()
vw.backgroundColor = .red
vw.frame = CGRect(x: 5, y: 5, width: 50, height: 50)
view.addSubview(vw)
}
}複製代碼
代碼把一個邊長爲50的正方形加入到x: 5, y: 5的位置上,位置相對於它的父視圖的左上腳點。若是咱們的相對點變化了,好比說但願把這個正方形以自身的右下腳點爲慘遭,放到相對於父視圖的右下腳點的的-5,-5的位置上的話,會產生些問題:java
解決此問題的要點在於,App只是聲明本身的位置關係,具體的座標有UIKit來計算。如今UIKit提供的AutoLayout技術就能夠解決此問題。app
就以此問題爲例,能夠去掉:ide
vw.frame = CGRect(x: 5, y: 5, width: 50, height: 50)複製代碼
改爲以下的約束:函數
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = Page()
self.window?.makeKeyAndVisible()
return true
}
}
class Page: UIViewController{
var vw : UIView!
override func viewDidLoad() {
super.viewDidLoad()
vw = UIView()
vw.backgroundColor = .red
view.addSubview(vw)
vw.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -5)
let verticalConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: -5)
let widthConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
let heightConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
}複製代碼
首先必須設置此視圖的屬性:佈局
vw.translatesAutoresizingMaskIntoConstraints = false複製代碼
這樣AutoLayout才能生效。隨後建立的第一約束:spa
let horizontalConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -5)複製代碼
看起來有些複雜,可是若是知道一個公式就更容易讀懂此代碼。NSLayoutConstraint用來建立閱讀,其函數參數標籤有:code
公式由此標籤指定以下:對象
item.attribute relatedBy toItem.attribute*multiplier + constant複製代碼
標籤relatedBy指定的是一個操做符號,此處爲「=」,所以此公式簡化爲:ip
item.attribute = toItem.attribute*multiplier + constant複製代碼
再次的把標籤帶入參數值,就是這樣:
vw.right = view.right*1 - 5複製代碼
讀出來的意思就是:
視圖vw的右邊x值約束爲視圖view的右邊x值乘以1再減去5複製代碼
因而能夠類推第二個約束爲正方形的下邊y值和父視圖的下邊y值的約束定義:
視圖vw的下邊y值約束爲視圖view的下邊y值乘以1再減去5複製代碼
此案例中,正方形的寬度則只是一個常數值,並不須要相對於任何視圖的任何屬性,所以建立類NSLayoutConstraint時,公式中:
item.attribute relatedBy toItem.attribute*multiplier + constant複製代碼
的toItem.attribute*multiplier總體是無心義的,而簡化爲:
item.attribute = constant複製代碼
這也就是代碼:
let widthConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)複製代碼
標籤toItem爲nil, 標籤attribute爲NSLayoutAttribute.notAnAttribute的含義。一樣的,正方形的高度也是如此分析。
使用自動佈局,一個視圖的位置的參照物再也不僅僅是父視圖的左上腳點,而是變得豐富多彩,依據不一樣的狀況有不一樣的選擇:
如此等等。所以以前的指定xy值的作法,就稱爲自動佈局方法的一個特殊案例。