MacDev 板


LINE

這是「純程式碼 Auto Layout 與概要教學」系列第二篇。總共會有三篇: * 從 setFrame 到 Auto Layout constraint * Visual Format Language (VFL) * 何時需要 UIStackView? 本系列文範例,都整理成 Swift Playground 在這專案裡 https://github.com/denkeni/Auto-Layout-Programmatically (由於批踢踢不方便貼程式碼,會精簡摘錄 含完整程式碼與後續文章更新,請到網頁版 https://goo.gl/AWOCI2 ) # 前言 純程式碼建立 Auto Layout constraint 在 iOS 6 剛推出時只有兩種方式 其一是前篇文所述的線性關係 其二即是 Visual Format Language (VFL) 到 iOS 9 之後才有第三種方式 NSLayoutAnchor 然而蘋果推出 Auto Layout 至今 幾乎所有官方文件都推廣透過 Interface Builder 來設定 constraint 這使得長期以來官方文件僅短短一頁的 VFL 成為被束之高閣的瑰寶 # Visual Format Language (VFL) VFL 可讀性不錯,尤其在相當複雜程度的排版更是如此, 因為 VFL 的根本基礎,就只有一段即見即所得的字串: ``` NSLayoutConstraint.constraints(withVisualFormat: VFLString, options: NSLayoutFormatOptions, metrics: [String : Any], views: [String : Any]) ``` 直接用實例來解釋這個 API 我們改用 Auto Layout VFL 重做前篇例子 subviewB 的排版方式 分別設定 top, bottom, left, right 如下: https://cdn-images-1.medium.com/max/800/1*PZarxIPo6anPxjm8VysOhw.png
```精簡版 VisualFormat: "V:|-(150)-[subviewB]-(150)-|" // V: Vertical VisualFormat: "H:|-(100)-[subviewB]-(100)-|" // H: Horizontal ``` 首先可以發現,VFL 其實就是自動幫我們生成多個 constraints 所以改用 += 來加入 constraints array 以中括號描述 view 以小括號描述數值 座標軸同樣是由上往下(V)、由左向右(H)的方向描述 直線 `|` 表示為 superview `V:|-(150)-[subviewB] `表示為 subviewB 與其 superview 的 top 相距 150pt `V:[subviewB]-(150)-|` 表示為 subviewB 與其 superview 的 bottom 相距 150pt 兩者合併起來就是相當直觀的 `V:|-(150)-[subviewB]-(150)-|` 多數人不使用 options 而採用預設的空值 [] metrics 是用來描述 VFL 字串中「數值常數」的對應字典 views 則是用來描述 VFL 字串中「view 變數」的對應字典 故前例也可以修改成這樣: ```精簡版 let metrics = ["v": 150, "h": 100] VisualFormat: "V:|-(v)-[subview]-(v)-|" VisualFormat: "H:|-(h)-[subview]-(h)-|" ``` 由此也會發現 只用 VFL 無法描述前篇例子 subviewA, subviewC 的排版方式 因為 VFL 無法描述 centerX, centerY 因此,在許多情況下 VFL 還是得合併使用 constraint 來正確描述 subview 我們改用 Auto Layout VFL + NSLayoutAnchor 重做前篇例子 subviewA, subviewC 的排版方式 分別設定 centerX, centerY 和 width, height 如下: ```精簡版 subviewA.centerXAnchor.constraint(equalTo: view.centerXAnchor) subviewA.centerYAnchor.constraint(equalTo: view.centerYAnchor) VisualFormat: "H:[subviewA(200)]" // width VisualFormat: "V:[subviewA(100)]" // height ``` 基於 VFL,也可以很容易地描述較為複雜的排版了: https://cdn-images-1.medium.com/max/800/1*_7pEUtg78EELsPmSXpL2UQ.png
```精簡版 let metrics = ["p": 15] // padding VisualFormat: "H:|-(p)-[subview1(100)]-(10)-[subview2(120)]-(10)-[subview3]-(p)-|" "V:|-(p)-[subview1]-(p)-|" "V:|-(p)-[subview2]-(p)-|" "V:|-(p)-[subview3]-(p)-|" ``` 當然,在描述更為複雜的二維排版時 由於一段 VFL 只能描述一維排版關係 經常需要組合多段 VFL 才能完整而正確地描述排版 # 番外篇:NSLayoutFormatOptions 這個選項可在描述 X 方向 VFL 時,提供 Y 方向排版的準則 反之亦然。 以下述為例: https://cdn-images-1.medium.com/max/800/1*pyc3FixPF8775DPTkQTnVQ.png
```精簡版 VisualFormat: "H:|-(15)-[subview1(100)]-(10)-[subview2(120)]-(10)-[subview3]-(15)-|", options: .alignAllTop, metrics: nil, views: viewsDict) VisualFormat: "V:[subview1(300)]" VisualFormat: "V:[subview2(200)]" VisualFormat: "V:[subview3(150)]" ``` # VFL Coding Style 以下是我自己偏好的 VFL Coding Style 原則,並藉此解釋 VFL 的相容語法: * view 間距常數值加上括號 * view 間距常數值為等式時,不加上 `==` ex. `[view1]-(15)-[view2]` 而非 `[view1]-15-[view2]` 或 `[view1]-(==15)-[view2]` 這也是考量了使用不等式時,必須加上括號才能運作 ex. `[view1]-(>=15)-[view2]` * view 間距常數值為 0 時,依然要標示出來 ex. `[view1]-(0)-[view2]` 而非 `[view1][view2]` ex. `|-(0)-[view]-(0)-|` 而非 `|[view]|` * 不使用預設的間距 ex. `[view1]-(8)-[view2]` 而非 `[view1]-[view2]`(兩者效果相同) P.S. 有一專案 [Swiftstraints](https://github.com/Skyvive/Swiftstraints) 將 VFL 精簡成僅需一段字串,字串內可直接取用變數, 便可省略了 metrics 與 views 參數。 -- 我最近寫了一個叫作「工作咖啡館」的 iOS App https://goo.gl/iBWJSs 我朋友拖拖拉拉也生出了 Android 版叫作「CaffeeTrip」 https://goo.gl/HnUQWQ --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 219.85.169.16
※ 文章網址: https://webptt.com/m.aspx?n=bbs/MacDev/M.1491279670.A.17A.html
1F:推 gogoqaz: 推 04/06 22:52
2F:推 seanbabby: 推 05/04 17:56
3F:推 Polestar: 推 05/13 00:09







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Gossiping站內搜尋

TOP