[译] 你 Ladar 中该珍藏的:iOS 布局语言

若是你在iOS开发时使用 Auto Layout 来纯代码布局的话,你很容易就会感到啰嗦和乏味。DSL(译者注:原意为「领域特定语言」,在本文中根据语境译为「布局语言」)可以将基础的API转换成能够简单、快速开发和阅读的代码。有不少这类布局语言支持 Auto Layout,甚至有几个还支持手动 frame 布局。前端

我能够给你推荐一些我偶然遇到而且保存到个人 Ladar 书签中的布局语言(别忘了你能够在 Github 中 star 这些库,而且能够自动更新到你的 Lardar 帐户中)。android

SnapKit [Swift] & Masonry [Objective-C]

如今我已经使用 SnapKit 一段时间了,在这以前是 Masonry。SnapKit 是 Masonry 的 Swift 版继承者,两者使用的是同一种构思,都值得使用。ios

SnapKit 使用闭包(Masonry 则用 block)和点语法来连接自动布局的约束需求。下面是一个使用 SnapKit 添加约束的例子:git

view.addSubview(label)
label.snp.makeConstraints { (make) in
    make.label.leading.bottom.equalToSuperview()
    make.top.equalTo(anotherView.snp.bottom).offset(12) // Label top == anotherView bottom + 12
    make.width.equalToSuperview().dividedBy(2).labeled("label width") // Label width == view width / 2
}
view.snp.makeConstraints { (make) in
    make.edges.equalToSuperview() // SnapKit offers some handy shortcuts like .edges and .size to constrain multiple attributes at once
}
复制代码

我特别喜欢 SnapKit 的一点是,你可使用点语法 .labeled() 来命名约束,当你的约束冲突时,能够在 Xcode 中显示出来。这对找到出问题的约束有很大帮助,以使得你的布局能够正常工做,可是你不须要由于这个来给每一个约束一个惟一的标签。github

EasyPeasy [Swift]

EasyPeasy 提供了一次性添加多个约束的好方法。在使用 SnapKit 时,你能够用 同一种 方法来约束视图的各个方向,好比:view.leading.trailing.equalToSuperview(),可是你不能把诸如 leadingtrailing 这样不一样的约束连接在一块儿。后端

在使用 EasyPeasy 时,你能够这样作:bash

myView.easy.layout(
  Width(200),
  Height(120)
)
复制代码

EasyPeasy 另外一个有趣的地方是能够给约束添加条件,好比:闭包

var isCenterAligned = true
view.easy.layout(
  Top(10),
  Bottom(10),
  Width(250),
  Left(10).when { !isCenterAligned },
  CenterX(0).when { isCenterAligned }
)
复制代码

在 iOS 里,你也可使用你正在添加约束的视图的 UITraitCollection 上下文,更轻松地来为不一样的设备和方向调整你的布局。app

Stevia [Swift]

Stevia 是 freshOS 的一部分,而 freshOS 是一个帮助 iOS 开发者在他们的项目中集合库文件的项目。Stevia 和 SnapKit 有许多类似点,但有一些不一样的地方让 Stevia 至关吸引人。框架

其中一个就是 Stevia 提供它本身的可视化布局 API。因此,若是你喜欢 Apple VFL 的可视化效果可是不想那么啰嗦、不想依赖于字符串和字典检查,Stevia 是一个很好的选择。这有一个 Stevia 文档中使用可视化布局 API 的简单例子:

layout(
    100,
    |-email-| ~ 80,
    8,
    |-password-forgot-| ~ 80,
    >=20,
    |login| ~ 80,
    0
)
复制代码

你也能够像 SnapKit 那样使用 Stevia,好比用点语法连接多个属性:

email.top(100).left(8).right(8).width(200).height(44)
image.fillContainer()
复制代码

你也可使用等式 API 来布局,像这样:

email.Top == 100
password.CenterY == forgot.CenterY
复制代码

Stevia 让我喜欢的一点是,你可使用像下面这样的方法同时约束多个视图:

alignHorizontally(password, forgot)
equalWidths(email, password)
复制代码

只需一点点设置,你就可使用 Stevia 的即时重载功能,让开发更快捷。

Mortar [Swift]

和 SnapKit 以及 Stevia 不一样的是,Mortar 压根不提供点语法。它有意地避免点语法来提高可读性。

但无论怎样,它仍是和 Stevia 同样提供了可视的布局 API,一样是一种用代码建立自动布局的简明的语法。

这是 Mortar 文档中列举的可视布局 API 例子:

viewA | viewB[==viewA] || viewC[==40] | 30 | viewD[~~1] | ~~1 | viewE[~~2]

// viewA has a size determined by its intrinsic content size
// viewA is separated from viewB by 0 points (| operator)
// viewB has a size equal to viewA
// viewB is separated from viewC by the default padding (8 points; || operator)
// viewC has a fixed size of 40
// viewC is separated from viewD by a space of 30 points
// viewD has a weighted size of 1
// viewD is separated fom viewE by a weighted space of 1
// viewE has a weighted size of 2
复制代码

Mortar 也容许你同时设置多个视图的约束,这点我认为很是有用。这里是用不一样方式建立 Mortar 约束的概览:

[view1, view2, view3].m_size |=| (100, 200)

/* Is equivalent to: */
[view1.m_size, view2.m_size, view3.m_size] |=| (100, 200)

/* Is equivalent to: */
view1.m_size |=| (100, 200)
view2.m_size |=| (100, 200)
view3.m_size |=| (100, 200)
复制代码

我对 Mortar 大量符号的使用有点失去了兴趣,可是符号的运用确实让语法很是简洁。我想若是你能够应付这些语法,你可使用 Mortar 更快、更简单的添加约束。其余很是好的地方是,Mortar 没有忽略其余布局库并不支持的约束属性,好比 firstBaseline

Bamboo [Swift]

虽然 Bamboo 看起来和我提到的其余库很类似,可是它确实有一些独特的地方,值得咱们探索。一个让我喜欢的方面是它的 fill 方法。对于初学者,你能够仅仅使用一个 fill() 来把当前视图的边缘贴在父视图的边缘上。可是你也能够调用好比 fillLeft() 来让视图的左、上、下边缘贴合到父视图上,或者使用 fillWidth() 来贴合视图的头和尾边缘。

另外一组我喜欢的方法是 before()after()above()below()。我常常考虑用这种方法定位个人视图,因此,像这样用代码表达约束和个人思考过程是同步的,这是一个很好的方式。每个这样的方法都有一个可选的间隔参数,因此你能够轻松地使用间隔参数在一个视图后面布局另外一个视图。

给你展现一个我喜欢的特性:你可使用 Bamboo 同时约束多个视图:

// 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) } [view1, view2, view3].bb.left() // align all left [view1, view2, view3].bb.width(10) // set width of all to 10 复制代码

Bamboo 一样提供一个优雅的选择,以便你在坐标轴上均匀地分布视图:

[view1, view2, view3].bb.distributeX(spacing: 10) // [view1]-10-[view2]-10-[view3]
复制代码

最后,当自动布局失效时,Bamboo 也提供了手动 frame 布局的近似语法

Cartography [Swift]

Cartography 使用基于闭包的方法来添加约束,每一个闭包能够同时约束多个视图。下面是文档中的例子:

constrain(view1, view2) { view1, view2 in
    view1.width   == (view1.superview!.width - 50) * 0.5
    view2.width   == view1.width - 50
    view1.height  == 40
    view2.height  == view1.height
    view1.centerX == view1.superview!.centerX
    view2.centerX == view1.centerX

    view1.top >= view1.superview!.top + 20
    view2.top == view1.bottom + 20
}
复制代码

你也能够一次只约束一个视图,好比:

constrain(view) { view in
    view.width  == 100
    view.height == 100
}
复制代码

你也能够将全部的约束放到一个闭包里,就像一个 ConstraintGroup

let group = constrain(button) { button in
    button.width  == 100
    button.height == 400
}
复制代码

或者只在闭包中保留一个约束:

var width: NSLayoutConstraint?

constrain(view) { view in
    width = (view.width == 200 ~ 100)
}
复制代码

就像本文中其余的布局语言,Cartography 也提供了 edgescentersize 之类的混合属性来提升效率。它也提供了简单的对齐多个视图的方法:

constrain(view1, view2, view3) { view1, view2, view3 in
    align(top: view1, view2, view3)
}
复制代码

均匀分布视图方面,和 Bamboo 很像:

constrain(view1, view2, view3) { view1, view2, view3 in
    distribute(by: 10, horizontally: view1, view2, view3)
}
复制代码

其余选择

你可能还会喜欢下面这些库:

  • LayoutKit [Swift, Objective-C],自动布局的另外一种选择,LinkedIn开发。
  • PinLayout [Swift],一个手动 frame 布局的布局语言。
  • FlexLayout [Swift],Yoga/Flexbox 的 Swift 版本接口, 由 PinLayout 背后的团队开发。
  • Layout [Swift],使用XML模板文件布局的框架。

我还发现了许多的自动布局语言,但并无添加到 Larder 中或在这里列举。大部分是由于它们要么太老而且没人维护,或者是太简单、没有特色。但这并不意味着它们没有用,只是我在寻找最有趣、最独特使用自动布局语法糖的方式罢了。

但愿你能够在这个列表里找到一些新的可尝试的东西!若是你认为我漏掉了值得探究的库,请在这个 Twitter @LarderApp 里和咱们分享。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索