一行代码实现自动布局(手动布局在一行中)。
快速查看
view.bb.centerX().below(view2).size(100)
与 iOS 9 API 等价
view.centerXAnchor.constraint(equalTo: view.superview!.centerXAnchor).isActive = true
view.topAnchor.constraint(equalTo: view2.bottomAnchor).isActive = true
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
view.heightAnchor.constraint(equalToConstant: 100).isActive = true
如你所见,Bamboo 消除了大量冗余代码。
- 使用链式风格,您只需一次性写出视图的名称。
- 所有方法都分组在
bb
扩展中,因此它们的名称可以简单且简短。 - 通常隐含了父视图和锚点。
- 更高级的方法,如
below()
和size()
使操作更简单。
安装
Carthage
github "wordlessj/Bamboo" ~> 1.0
CocoaPods
pod 'Bamboo', '~> 1.0'
用法
基础知识
在 UIView
和 UILayoutGuide
上的所有基本锚点都提供了不带后缀 Anchor
的形式,例如 left
而不是 leftAnchor
。
// view.left == superview.left
view.bb.left()
// Or use it on UILayoutGuide.
layoutGuide.bb.left()
要指定另一个视图的对应锚点,只需将视图传递给方法。
// view1.left == view2.left
view1.bb.left(view2)
当然,您也可以使用特定的锚点。
// view1.left == view2.right
view1.bb.left(view2.rightAnchor)
使用操作符 +
或 -
添加常量是非常直接的。
// view1.left == view2.right + 10
view1.bb.left(view2.rightAnchor + 10)
// Specific view or anchor can be omitted.
// view.left == superview.left + 10
view.bb.left(10)
对于维度锚点,当只指定了常量时,它将维度设置为常量,而不是匹配到父视图。
// view.width == 10
view.bb.width(10)
width()
和width(0)
是不同的,前者与父视图匹配,后者设置为 0。
在 iOS 11 中,您可以代替常量使用 SystemSpacing
,将乘数传递给初始化器,只支持 +
操作符。
// view1.left == view2.right + 2 * SystemSpacing
view1.bb.left(view2.rightAnchor + SystemSpacing(2))
类似地,使用 >=
或 <=
来指定等式。
// view1.left >= view2.right + 10
view1.bb.left(>=view2.rightAnchor + 10)
要指定优先级,请使用操作符 ~
。
// view1.left == view2.right + 10 (priority 500)
view1.bb.left(view2.rightAnchor + 10 ~ 500)
对于维度锚点,可以使用 *
或 /
指定乘数。
// view1.width == 2 * view2.width
view1.bb.width(2 * view2)
表达式
表达式传递到基本锚点方法。完全形式
( >= or <= ) item + constant ~ priority
对于维度锚点
( >= or <= ) item * multiplier + constant ~ priority
item
可以是 UIView
、UILayoutGuide
或 NSLayoutAnchor
。您可以使用 /
和 -
替代 *
和 +
。如果未指定等式,则可以在 item
前放置 multiplier
来使其更类似于线性函数。可以创建更复杂的表达式,但为了简单起见,不推荐这样做。
约束
您可以获取用于以后使用的方法生成的单个约束。
let c: NSLayoutConstraint = view.bb.left().constraint
或获取从链中累积的所有约束。
let c: [NSLayoutConstraint] = view.bb.left().top().constraints
激活和禁用
约束可以被启用和禁用,以便更好地控制布局变化。
// Deactivate after creation.
let c: [NSLayoutConstraint] = view.bb.left().top().constraints.deactivate()
// Activate later when appropriate.
c.activate()
高级方法
宽高比
// view.width == 2 * view.height
view.bb.aspectRatio(2)
居中和尺寸
这两种方法与基本锚定方法类似。
center()
,包括centerX
和centerY
。size()
,包括width
和height
。
还有两种设置尺寸的方法。
let cgSize: CGSize
view.bb.size(cgSize)
view.bb.size(width: 10, height: 20)
填充
// Pin all edges.
fill()
// Pin corresponding edge and adjacent edges.
// e.g., fillLeft() pin left, top and bottom.
fill[Left|Right|Top|Bottom|Leading|Trailing]()
// Pin edges on corresponding axis.
// e.g., fillWidth() pin leading and trailing.
fill[Width|Height]()
所有填充方法接受两个可选参数,第一个是填充的视图或 UILayoutGuide
,如果为 nil
则为其父视图,第二个是 UIEdgeInsets
。
// view1 fills view2 with insets.
let insets: UIEdgeInsets
view1.bb.fill(view2, insets: insets)
// If all edge insets are the same, you can pass a single value.
// view1 fills view2 with insets 10.
view1.bb.fill(view2, insets: 10)
周围
before()
after()
above()
below()
这些方法和填充方法类似,两个可选参数,除了第二个是间距。
// view1.trailing == view2.leading - 10
view1.bb.before(view2, spacing: 10)
偏移
在iOS 10中,使用 -
运算符在两个轴锚之间创建偏移锚定,然后用 offset()
创建约束。在使用 bb
之前,使用的视图是什么无关紧要。
// view2.left - view1.right == view3.left - view2.right
view1.bb.offset(view2.leftAnchor - view1.rightAnchor, view3.leftAnchor - view2.rightAnchor)
多个项目
你可以同时约束多个项目。有许多基本方法都以此为基础。
// Constrain on each item.
// e.g., Set each item's width to 10.
[view1, view2, view3].bb.each {
$0.bb.width(10)
}
// Constrain between every two items.
// e.g., view1.left == view2.left, view2.left == view3.left
[view1, view2, view3].bb.between {
$0.bb.left($1)
}
对单个项目的基本方法在多个项目上也可用。
// Anchor methods take no arguments and align all items' corresponding anchor.
// e.g., Align all views' left.
[view1, view2, view3].bb.left()
// For dimension anchors, you can set values for all items.
// e.g., Set all views' width to 10.
[view1, view2, view3].bb.width(10)
你可以使用固定间距或等间距沿一个轴分配项目。
distributeX()
distributeY()
distributeXEqualSpacing()
distributeYEqualSpacing()
// [view1]-10-[view2]-10-[view3]
[view1, view2, view3].bb.distributeX(spacing: 10)
所有distribute
方法都包含一个可选的inset
参数,你可以指定不添加边距、固定边距或等边距。
// |-[view1]-[view2]-[view3]-|, spacings are all equal.
[view1, view2, view3].bb.distributeXEqualSpacing(inset: .equal)
分组
如果你想要在响应某些事件时激活/禁用一组约束,可以使用group()
将约束收集到数组中。
let constraints: [NSLayoutConstraint] = group {
view1.bb.fill()
view2.bb.left().top().size(100)
view3.bb.fillBottom().height(100)
}
手动布局
为什么有自动布局还要手动布局呢?自动布局虽然不错,但有一些性能问题,这时你可能想要切换到手动布局。
熊猫
熊猫是一个创建视图层次的框架,与Bamboo配合使用,它们可以让在代码中创建视图变得非常简单。
许可证
Bamboo遵从MIT许可证发布。详细信息请参阅LICENSE。