FlooidLayout
FloodLayout 是一个自动布局 DSL,它通过使用自定义运算符帮助您编写更直观和易于理解的代码。例如,以下标准的自动布局代码
NSLayoutConstraint.activate([
image.centerXAnchor.constraint(equalTo: container.centerXAnchor),
image.topAnchor.constraint(equalTo: container.topAnchor, constant: 20),
image.widthAnchor.constraint(equalTo: container.widthAnchor, constant: -2*20),
image.heightAnchor.constraint(equalTo: image.widthAnchor, multiplier: 0.6)
])
可以写成
image.constraints { $0
--| $1.centerXAnchor == container.centerXAnchor
--| $1.topAnchor == container.topAnchor + 20
--| $1.widthAnchor == container.widthAnchor -- 20
--| $1.heightAnchor == $0.widthAnchor * 0.6
}
安装
Cocoapods
将以下行添加到您的 Podfile 中
pod 'FlooidLayout', '~> 1.0.2.preXcode11'
Swift 包管理器
将以下依赖项添加到您的 Package.swift 中(或当通过 Xcode 11 整合时,使用以下 URL 和版本规则)
.package(url: "https://github.com/martin-lalev/FlooidLayout.git", .upToNextMajor(from: "1.0.2.preXcode11"))
它是如何工作的
FlooidLayout使用==
、<=
或>=
运算符,以左侧为基础锚点,右侧为一个布局表达式来构建NSLayoutConstraint
。布局表达式可以仅是一个常量(如果左侧是一个尺寸锚点),或者由另一个锚点、可选的乘数(* <multiplier value>
)和可选的常量(+/- <constant value>
)的组合。
宽度和高度锚点也可以用
++
或--
为其常量赋值,这相当于将常数值乘以2。当你想在两侧都表示某种填充或边距时,这非常有用。
为了让布局构建更简单,所有的UIView
和UILayoutGuide
都有一个constraints
辅助方法,它接受一个函数构建闭包。闭包只有一个参数——在constraints
方法上被调用的对象。这样,你可以将相关的约束组合到单个代码块中。
修改和变量赋值
FlooidLayout 允许你对部分约束属性进行内联更改,并将约束存储在变量中,从而保持你的自动布局代码的声明性。
分配自定义优先级
--| $1.heightAnchor == $1.widthAnchor * 0.6 --! .priority(.defaultHigh)
分配标识符
--| $1.centerXAnchor == container.centerXAnchor --! .identifier("iconCenterX")
激活
icon.centerXAnchor == container.centerXAnchor --! .activated
仅在声明约束不在
constraints
方法之外时使用,因为它将自动激活函数构建块中的所有约束。
存储在变量中
--| $1.topAnchor == container.topAnchor + 20 --> imageTopConstraint
链式操作
所有上述操作都可以通过链式操作组合在一起,唯一限制是赋值必须在声明的基础上进行
--| $1.heightAnchor == $1.widthAnchor * 0.6 --! .priority(.defaultHigh) --! .identifier("iconHeight") --> iconHeightConstraint
额外的锚点
FlooidLayout 提供了一些额外的“锚点”,这些锚点可以让您的锚点声明更加丰富
sizeAnchor
修改宽度和高度锚点
// Constant assignment
--| $1.sizeAnchor == CGSize(width: 30, height: 30)
// Another sizeAnchor assignment
--| $1.sizeAnchor == container.sizeAnchor
// Expanding both dimensions
--| $1.sizeAnchor == container.sizeAnchor + 20
// Shrinking both dimensions (the constant is multipled by two in this example)
--| $1.sizeAnchor == container.sizeAnchor -- 20
// Scaling both dimensions
--| $1.sizeAnchor == container.sizeAnchor * 0.5
// Expanding each dimensions separately
--| $1.sizeAnchor == container.sizeAnchor + (width: 20, height: 40)
// Shrinking each dimensions separately (the constants are multipled by two in this example)
--| $1.sizeAnchor == container.sizeAnchor -- (width: 20, height: 10)
// Scaling each dimensions separately
--| $1.sizeAnchor == container.sizeAnchor * (width: 0.5, height: 0.4)
centerAnchor
修改中心 x 和 y 锚点。类似的位置锚点还包括如 leadingTopAnchor
、centerBottomAnchor
、rightCenterAnchor
等。
// Another locationAnchor assignment
--| $1.centerAnchor == container.centerAnchor
// Moving both axis
--| $1.leadingTopAnchor == icon.leadingTopAnchor + 20
// Moving each axis separately
--| $1.leadingCenterAnchor == siblingView.trailingCenterAnchor + (x: 10, y: 0)
edgesAnchor
修改顶部、底部、前导和尾部锚点
// Another locationAnchor assignment
--| $1.edgesAnchor == container.edgesAnchor
// Insetting all edges equally
--| $1.edgesAnchor == container.edgesAnchor -- 10
// Insetting edges separately per axis
--| $1.edgesAnchor == container.edgesAnchor -- (horizontally: 20, vertically: 10)
// Insetting each edge separately
--| $1.edgesAnchor == container.edgesAnchor -- (leading: 5, trailing: 15, top: 10, bottom: 20)
horizontalEdgesAnchor
修改首尾锚点
// Another horizontalEdgesAnchor assignment
--| $1.horizontalEdgesAnchor == container.horizontalEdgesAnchor
// Insetting both edges equally
--| $1.horizontalEdgesAnchor == container.horizontalEdgesAnchor -- 10
// Insetting each edge separately
--| $1.horizontalEdgesAnchor == container.horizontalEdgesAnchor -- (leading: 5, trailing: 15)
verticalEdgesAnchor
修改上下锚点
// Another verticalEdgesAnchor assignment
--| $1.verticalEdgesAnchor == container.verticalEdgesAnchor
// Insetting all edges equally
--| $1.verticalEdgesAnchor == container.verticalEdgesAnchor -- 10
// Insetting each edge separately
--| $1.verticalEdgesAnchor == container.verticalEdgesAnchor -- (top: 10, bottom: 20)