Swift iOS:AutoLayout 快速介绍

AutoLayout

典型的,加入一个子视图的做法就是创建实例,指定位置,然后把它加入到视图里面来。在指定位置的代码处,一般就是设置frame属性即可,就像这样:

    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的位置上的话,会产生些问题:

  1. 正方形的左上角的x和y的值就得自己计算
  2. 当手机旋转时,屏幕的横向长度和纵向长度就变了,因此x和y的值也得自己重新计算

解决此问题的要点在于,App只是声明自己的位置关系,具体的坐标有UIKit来计算。现在UIKit提供的AutoLayout技术就可以解决此问题。

就以此问题为例,可以去掉:

    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才能生效。随后创建的第一约束:

    let horizontalConstraint = NSLayoutConstraint(item: vw, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -5)复制代码

看起来有些复杂,但是如果知道一个公式就更容易读懂此代码。NSLayoutConstraint用来创建阅读,其函数参数标签有:

  1. item 要定位的视图对象
  2. attribute 要定位的视图对象的属性
  3. relatedBy 相对关系,也就是公式内的操作符号,最常用的就是等于,但是也可以使用大于小于等操作符号
  4. toItem 用来对定位点的视图对象
  5. attribute 用来对定位点的视图对象的属性
  6. multiplier 系数
  7. constant 常数

公式由此标签指定如下:

    item.attribute relatedBy toItem.attribute*multiplier + constant复制代码

标签relatedBy指定的是一个操作符号,此处为“=”,因此此公式简化为:

    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的含义。同样的,正方形的高度也是如此分析。

使用自动布局,一个视图的位置的参照物不再仅仅是父视图的左上脚点,而是变得丰富多彩,依据不同的情况有不同的选择:

  1. 指定视图的中心点和父视图重合
  2. 指定一个视图和它的兄弟视图紧靠
  3. 靠左靠右靠上靠下

如此等等。因此之前的指定xy值的做法,就称为自动布局方法的一个特殊案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值