How to Package Code Auto Layout tool?
繼上一篇 如何使用 Code Auto Layout ,我們發現 Code Auto Layout 的程式碼太長,太多元件會造成難以閱讀,所以我們今天打算來封裝 Code Auto Layout 工具。

思考與實作
// 加入 Subview
addSubview(infoTopStackView)
// 設置 layout
infoTopStackView.translatesAutoresizingMaskIntoConstraints = false
// infoTopStackView topAnchor,對齊 cell topAnchor,並啟動約束
infoTopStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
// infoTopStackView leadingAnchor,對齊 cell leadingAnchor,並啟動約束
infoTopStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
// infoTopStackView bottomAnchor,對齊 cell bottomAnchor,並啟動約束
infoTopStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
// infoTopStackView trailingAnchor,對齊 cell trailingAnchor,並啟動約束
infoTopStackView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
我們先觀察一下,基本會用到的屬性有:
- topAnchor
- leadingAnchor
- bottomAnchor
- trailingAnchor
- widthAnchor
- heightAnchor
- 每次都要關閉的 translatesAutoresizingMaskIntoConstraints
- constant 的邊界值
我們需要 layout 的對象,基本上都屬於 View,所以我們打算在 View
上使用 Extension
讓我們先建立 extension UIView
extension UIView {
}
接著我們建立一個 func
並提供以上方法的參數接口
/**
for view constraint
- Parameter top: 上邊界約束
- Parameter leading: 左邊屆約束
- Parameter bottom: 下邊界約束
- Parameter trailing: 右邊界約束
- Parameter padding: constant with UIEdgeInsets
- Parameter size: widthAnchor, heightAnchor with CGSize
*/
func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
}
接著我們開始接入 constraint
/**
for view constraint
- Parameter top: 上邊界約束
- Parameter leading: 左邊屆約束
- Parameter bottom: 下邊界約束
- Parameter trailing: 右邊界約束
- Parameter padding: constant with UIEdgeInsets
- Parameter size: widthAnchor, heightAnchor with CGSize
*/
func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
// 關閉 translatesAutoresizingMaskIntoConstraints
translatesAutoresizingMaskIntoConstraints = false
// 如果有,開啟約束
if let top = top {
topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
}
if let leading = leading {
leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
}
if let trailing = trailing {
trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
}
// 如果不=0 開啟約束
if size.width != 0 {
widthAnchor.constraint(equalToConstant: size.width).isActive = true
}
// 如果不=0 開啟約束
if size.height != 0 {
heightAnchor.constraint(equalToConstant: size.height).isActive = true
}
}
因為我們常常會用到填滿視窗,我們可以在封裝一個方法
func fillSuperview(padding: UIEdgeInsets = .zero) {
anchor(top: superview?.topAnchor, leading: superview?.leadingAnchor, bottom: superview?.bottomAnchor, trailing: superview?.trailingAnchor, padding: padding)
}
最後我們的 extension 會像
extension UIView {
func fillSuperview(padding: UIEdgeInsets = .zero) {
anchor(top: superview?.topAnchor, leading: superview?.leadingAnchor, bottom: superview?.bottomAnchor, trailing: superview?.trailingAnchor, padding: padding)
}
/**
for view constraint
- Parameter top: 上邊界約束
- Parameter leading: 左邊屆約束
- Parameter bottom: 下邊界約束
- Parameter trailing: 右邊界約束
- Parameter padding: constant with UIEdgeInsets
- Parameter size: widthAnchor, heightAnchor with CGSize
*/
func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
translatesAutoresizingMaskIntoConstraints = false
if let top = top {
topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
}
if let leading = leading {
leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
}
if let trailing = trailing {
trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
}
if size.width != 0 {
widthAnchor.constraint(equalToConstant: size.width).isActive = true
}
if size.height != 0 {
heightAnchor.constraint(equalToConstant: size.height).isActive = true
}
}
}
實際使用
回到我們的 SearchResultCellView
(繼上一篇 如何使用 Code Auto Layout),替換我們封裝的方法。
舊方法如下:
// 加入 Subview
addSubview(infoTopStackView)
// 設置 layout
infoTopStackView.translatesAutoresizingMaskIntoConstraints = false
// infoTopStackView topAnchor,對齊 cell topAnchor,並啟動約束
infoTopStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
// infoTopStackView leadingAnchor,對齊 cell leadingAnchor,並啟動約束
infoTopStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
// infoTopStackView bottomAnchor,對齊 cell bottomAnchor,並啟動約束
infoTopStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
// infoTopStackView trailingAnchor,對齊 cell trailingAnchor,並啟動約束
infoTopStackView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
新方法:
addSubview(overallStackView)
overallStackView.fillSuperview(padding: .init(top: 16, left: 16, bottom: 16, right: 16))
是不是簡單了許多呢!
如果你需要範例輔助您,請點此專案
感謝您的閱讀,祝你有個美好的 Coding
yasuoyuhao 2019/05/11
如果喜歡我的文章,可以按下喜歡或追隨讓我知道呦,更歡迎許多大神指點討論。感謝您的閱讀。
部落格:yasuoyuhao’s Area