LayoutGuide的使用
2020-03-28 本文已影响0人
coderhlt
一、topLayoutGuide和bottomLayoutGuide
extension UIViewController {
open var topLayoutGuide: UILayoutSupport { get }
open var bottomLayoutGuide: UILayoutSupport { get }
}
topLayoutGuide和bottomLayoutGuide是UIViewController的属性,ios7开始用于在自动布局时,帮助开发者避开顶部的状态栏,导航栏以及底部的tabbar等。
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print(self.topLayoutGuide.topAnchor)
print(self.topLayoutGuide.bottomAnchor)
print(self.bottomLayoutGuide.topAnchor)
print(self.bottomLayoutGuide.bottomAnchor)
print(self.topLayoutGuide.length)//20
print(self.bottomLayoutGuide.length)//0
let myview = UIView()
self.view.addSubview(myview)
myview.backgroundColor = .red
myview.snp.makeConstraints { (make) in
make.top.equalTo(self.topLayoutGuide.snp.bottom)
make.width.equalTo(100)
make.height.equalTo(40)
make.centerX.equalToSuperview()
}
}
}
- 对于每一个UIViewController,都会有一个bottomLayoutGuide是UIViewController的属性,在自动布局时,可以通过设置控制器的bottomLayoutGuide进行约束,来避开顶部的状态栏,导航栏以及底部的tabbar等。
- iOS11以后 topLayoutGuide和bottomLayoutGuide废弃,用safeAreaLayoutGuide代替
二、 UILayoutGuide
iOS9开始,苹果新增加了一个UILayoutGuide的类。UILayoutGuide用于提供一个矩形区域可以用Auto Layout来定制一些约束特性,作为一个虚拟的view使用。
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let view = UIView()
self.view.addSubview(view)
view.backgroundColor = .red
view.snp.makeConstraints { (make) in
make.width.equalTo(300)
make.height.equalTo(300)
make.centerX.equalTo(self.view)
make.top.equalTo(self.topLayoutGuide.snp.bottom)
}
let space1 = UILayoutGuide()
view.addLayoutGuide(space1)
space1.snp.makeConstraints { (make) in
make.top.equalTo(view.snp.top).offset(10)
make.left.equalToSuperview().offset(10)
make.right.equalToSuperview().offset(-10)
make.height.equalTo(100)
}
let yelloview = UIView()
yelloview.backgroundColor = .yellow
view.addSubview(yelloview)
yelloview.snp.makeConstraints { (make) in
make.top.equalTo(space1)
make.left.right.bottom.equalTo(space1)
}
print(view.layoutGuides)
print(view.subviews)
print(space1.owningView)
}
}
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let container = UILayoutGuide()
self.view.addLayoutGuide(container)
container.snp.makeConstraints { (make) in
make.height.equalTo(20)
make.top.equalTo(self.topLayoutGuide.snp.bottom).offset(100)
make.centerX.equalToSuperview()
}
let redView = UIView()
redView.backgroundColor = .red
self.view.addSubview(redView)
redView.snp.makeConstraints { (make) in
make.top.equalTo(container)
make.left.equalTo(container)
make.width.equalTo(30)
make.bottom.equalTo(container)
}
let yellowView = UIView()
yellowView.backgroundColor = .yellow
self.view.addSubview(yellowView)
yellowView.snp.makeConstraints { (make) in
make.left.equalTo(redView.snp.right).offset(10)
make.width.equalTo(65);
make.top.bottom.equalTo(container)
make.right.equalTo(container)
}
}
}
- 当我们需要一个虚拟View帮助的事情都可以交给UILayoutGuide来做。UILayoutGuide并没有真正的创建一个View,只是创建了一个矩形空间,只在进行auto layout时参与进来计算,它没有参与视图层次结构,也不会影响事件的传递,更高效、更轻量级。
三、safeAreaLayoutGuide
iOS11又引入了一个Safe Area(安全区域)的概念,苹果果建议在这个安全区域内放置UI控件。这个安全区域的范围其实就是整个屏幕隔离出状态栏,导航栏,tabar,以及iPhone X顶部刘海,底部虚拟home手势区域的范围。
从这个介绍可以看得出,所谓的Safe Area其实也就是升级版本的topLayoutGuide/bottomLayoutGuide,以前只能限制top/bottom的Layout,现在更加强大了。
extension UIView {
var safeAreaLayoutGuide: UILayoutGuide { get }
var safeAreaInsets: UIEdgeInsets { get }
}
class ViewController: UIViewController {
var redView:UIView?
override func viewDidLoad() {
self.redView = UIView()
self.view.addSubview(self.redView!)
self.redView?.backgroundColor = .red
self.redView?.snp.makeConstraints({ (make) in
make.top.equalTo(self.topLayoutGuide.snp.bottom).offset(-30);
make.width.equalTo(100)
make.height.equalTo(100)
make.left.equalTo(self.view).offset(20)
})
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print(self.view.safeAreaLayoutGuide)
self.view.backgroundColor = .yellow
print(self.view.safeAreaLayoutGuide.layoutFrame) (0.0, 44.0, 414.0, 818.0)
print(self.redView?.safeAreaLayoutGuide.layoutFrame) (0.0, 30.0, 100.0, 70.0)
print(self.view.safeAreaInsets) # UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
print(self.redView!.safeAreaInsets) #UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
}
}
注:代码是在以xr模拟器测试
- 系统会为每个UIView创建一个safeAreaLayoutGuide(安全区域)
- safeAreaInsets表示的是view的边界与自身安全区域的间距
class ViewController: UIViewController {
var redView:UIView?
override func viewDidLoad() {
self.redView = UIView()
self.view.addSubview(self.redView!)
self.redView?.backgroundColor = .red
self.redView?.snp.makeConstraints({ (make) in
make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top).offset(30);
make.width.equalTo(100)
make.height.equalTo(100)
make.left.equalTo(self.view).offset(20)
})
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print(self.view.safeAreaLayoutGuide)
self.view.backgroundColor = .yellow
print(self.view.safeAreaLayoutGuide.layoutFrame) (0.0, 44.0, 414.0, 818.0)
print(self.redView!.safeAreaLayoutGuide.layoutFrame) (0.0, 0.0, 100.0, 100.0)
print(self.view.safeAreaInsets) UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
print(self.redView!.safeAreaInsets) UIEdgeInsets(top: 0, left: 0.0, bottom: 34.0, right: 0.0)
}
}
- 在自动布局时就可以相对于view的安全区域做约束,有效的避开顶部的状态栏,导航栏以及底部的tabbar等。