Swift iOS:AutoLayout 快速介绍

AutoLayout

典型的,加入一个子视图的作法就是建立实例,指定位置,而后把它加入到视图里面来。在指定位置的代码处,通常就是设置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

  1. 正方形的左上角的x和y的值就得本身计算
  2. 当手机旋转时,屏幕的横向长度和纵向长度就变了,所以x和y的值也得本身从新计算

解决此问题的要点在于,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

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

公式由此标签指定以下:对象

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

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

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

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

相关文章
相关标签/搜索