Reference website 该教程源自翻译:
Git repository
我们首先通过代码创建几个label,然后利用Auto Layout来对label进行位置调整。
将如下代码放入ViewDidLoad方法中:
override func viewDidLoad() {
super.viewDidLoad()
let label1 = UILabel()
label1.translatesAutoresizingMaskIntoConstraints = false
label1.backgroundColor = UIColor.red
label1.text = "THESE"
let label2 = UILabel()
label2.translatesAutoresizingMaskIntoConstraints = false
label2.backgroundColor = UIColor.cyan
label2.text = "ARE"
let label3 = UILabel()
label3.translatesAutoresizingMaskIntoConstraints = false
label3.backgroundColor = UIColor.yellow
label3.text = "SOME"
let label4 = UILabel()
label4.translatesAutoresizingMaskIntoConstraints = false
label4.backgroundColor = UIColor.green
label4.text = "AWESOME"
let label5 = UILabel()
label5.translatesAutoresizingMaskIntoConstraints = false
label5.backgroundColor = UIColor.orange
label5.text = "LABELS"
view.addSubview(label1)
view.addSubview(label2)
view.addSubview(label3)
view.addSubview(label4)
view.addSubview(label5)
}
将下面这一行添加到ViewDidLoad方法下面:
override var prefersStatusBarHidden: Bool {
return true
}
let label1 = UILabel()
用代码创建一个UILabel
translatesAutoresizingMaskIntoConstraints = false
UI布局主要有三种方法,第一种是纯代码手工调整控件的位置(frame);第二种是利用autoresizing mask;第三种是Auto Layout。当控件被代码创建时,它的autoresizing 将被设置为UIViewAutoresizingNone, translatesAutoresizingMaskIntoConstraints默认设置为true。这样以来,如果不给View的autoresizing mask重新赋值的话,View的显示位置是:将UIViewAutoresizingNone翻译成Cosntraints,然后根据该Constraints决定View的位置。然而在我们这个例子中,我们是需要通过Constraints直接来决定View的显示位置,而不是利用autoresizing mask,所以这里要禁止掉translatesAutoresizingMaskIntoConstraints,即如上代码。
label1.backgroundColor = UIColor.red
将创建的label1的背景颜色设置为红色。
label1.text = "THESE"
将label1的显示内容,设置为"THESE"字符串。
view.addSubview(label1)
将label1添加到控制器所包含的view里面。创建控件后,必须把它添加到当前显示的View里面,这样才能够让控件正常显示出来。
override var prefersStatusBarHidden: Bool {
return true
}
前面override的意思就是重写,所以这上面的代码的意思就是重写父类的属性prefersStatusBarHidden,这里把这个属性重写为true。这样,显示的时候,就将statusBar隐藏掉。statusBar是什么呢?就是苹果手机里面用来显示网络运营商、Wi-Fi强度、蓝牙是否开启、电池电量等这些图标等区域。
运行以上代码,你将会看到“LABELS ME",以上的五个Label重叠在来一起。分析为什么会出现这种情况。
1. 这些控件都是通过代码创建的,所以并没有任何Constraints来约束控件。
2. 这里已经将translatesAutoresizingMaskIntoConstraints禁止掉了,所以并没有autoresizing mask来决定控件的位置。
3. 三种lay out中只剩下默认frame的默认值,来决定View的位置了。frame的origin应该是(0,0)所以,它们都挤在了父视图的左上角。而大小是系统根据Label显示的内容来决定其大小。
分析完毕。
let viewsDictionary = ["label1":label1,"label2":label2,"label3":label3,"label4":label4,"label5":label5]
将上面创建的五个label放入到了一个字典里面。这样我们就可以根据label的名字来引用相应的label了。比如说,我想引用第三个label,即label3。就可以用如下代码来实现
let wantedLabel = viewsDictionary["label3"]
很简单吧!
接下来把以下语句放到viewDictionary下面
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[label1]|", options:[],metrics:nil,view:viewsDictionary))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[label2]|", options:[],metrics:nil,view:viewsDictionary))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[label3]|", options:[],metrics:nil,view:viewsDictionary))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[label4]|", options:[],metrics:nil,view:viewsDictionary))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[label5]|", options:[],metrics:nil,view:viewsDictionary))
for label in viewsDictionary {
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"H:|[\(label)]|",options:[],metrics:nil,view:viewsDictionary))
}
NSLayoutConstraint.constraints(withVisualFormat:)这是自动布局的方法,是将Visual Format Language转化为一系列的约束的方法。
看完简单的再来看复杂一点的Visual Format Language, “H|[label1]|"是歌字符串,描述多了我们想如何布局。Visual Format Language被转化为Constraints,然后就被添加到View上去了。
H: 表示我们定义的是水平布局约束。
|: 表示的是view的边缘。
[label]: 是一个可视化方式,表示“把label1放到这里”。可以把方括号[]想做是label的边缘。
所以"H|[label1]|",表示的意思是:我想水平放置,边缘挨着边缘的把label1放在view里面。
结下来我们给这些label添加一个垂直约束。所以将如下代码放到上面的for语句下面:
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:"V:|[label1]-[label2]-[label3]-[label4]-[label5]",options:[],metrics:nil,views:viewsDictionary))
这里就遇到了两个新东西如下:
V:表示垂直布局。
-: 表示十个像素点的间隔。
"V:|[label1]-[label2]-[label3]-[label4]-[label5]"表示垂直布局,从上往下label以十个像素点的间隔依次往下排列。
注意:最末尾没有加“|”这个符号噢!