[譯] 你 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前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索