目標(biāo)
使用DeclareLayoutSwift來實現(xiàn)界面,代碼非常簡短,完全手寫代碼,不使用Storyboard和xib,也不使用約束。
要實現(xiàn)的效果:
要實現(xiàn)的效果
1.導(dǎo)航欄

nav.jpg
1.1 導(dǎo)航欄結(jié)構(gòu)分析

釘釘-消息.png
func createTitleView(title:String){
self.navigationController?.navigationBar.barTintColor = .white
let titleView = HostView {
Grid(.columns <- [.star(1),.auto]){ // ①
[Label(.text <- title, .fontSize <- 20),//②
StackPanel(.gridColumnIndex <- 1,.orientation <- .Horizontal) {//③
[Button(.image <- #imageLiteral(resourceName: "Msg_nav1")),//④
Button(.image <- #imageLiteral(resourceName: "Msg_nav2"), .margin <- Insets(vertical: 0, horizontal: 20)),
Button(.image <- #imageLiteral(resourceName: "Msg_nav3"))]
}]
}
}
self.navigationItem.titleView = titleView
}
①
- 使用Grid,將導(dǎo)航欄分成2列
- 第2列為自動(.auto,根據(jù)內(nèi)容設(shè)置寬度),用來放置右側(cè)圖標(biāo)。因為這一列是根據(jù)內(nèi)容自動適應(yīng)寬度的,增加圖標(biāo)或減少圖標(biāo)時不需要修改
- 第1列占據(jù)剩下寬度。
.star(1)的表示這一列是按比例分配。如:[.star(1),.star(2)]表示按1:2分配空間。這里沒有多個列用.star表示,所以第1列會占用所有剩下空間。
②
- 聲明一個Label,并設(shè)置文本和字體大小
- Label是Grid的子元素
- 由于位于Grid中,可以設(shè)置其所在的行或列,不設(shè)置默認(rèn)不第1行第1列
③
-
StackPanel表示一個水平或豎直方向的布局,這里設(shè)置為水平方向
.orientation <- .Horizontal,表示把子元素從左到右水平排列。 - 將StackPanel放到
Grid的第2列(.gridColumnIndex <- 1)
④
- 創(chuàng)建Button,并設(shè)置Button的圖片
- 也可以寫為
Button(.image <- "Msg_nav1")
2. 創(chuàng)建UITableView Cell

cell.jpg
2.1 Cell結(jié)構(gòu)分析

Cell結(jié)構(gòu)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let element = Grid(.columns <- [.auto, .star(1)], .padding <- Insets(vertical: 8, horizontal: 20)) {
[Image(.width <- 50, .image <- #imageLiteral(resourceName: "Msg_List"), .margin <- Insets(right: 10)),
StackPanel(.gridColumnIndex <- 1) {
[Grid(.columns <- [.star(1), .auto]) {
[Label(.text <- "釘釘運(yùn)動", .fontSize <- 17),
Label(.gridColumnIndex <- 1, .text <- "下午 8:36", .fontSize <- 13, .textColor <- UIColor(white: 0.8, alpha: 1))]
},
Label(.text <- "IT技術(shù)中心 獲得3月24日 XXX有限公司全員步數(shù)第一", .fontSize <- 15, .textColor <- .gray, .margin <- Insets(top: 8))]
}]
}
return tableView.makeCell(element: element)
}
padding和margin分別定義內(nèi)邊距和外邊距類型為Insets(UIEdgeInsets)
完整代碼
import DeclareLayoutSwift
import UIKit
class MessageVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
self.createTitleView(title: "釘釘")
self.view.hostElement {
Table(.delegate <- self, .dataSource <- self)
}
}
func createTitleView(title: String) {
self.navigationController?.navigationBar.barTintColor = .white
let titleView = HostView {
Grid(.columns <- [.star(1), .auto]) {
[Label(.text <- title, .fontSize <- 20),
StackPanel(.gridColumnIndex <- 1, .orientation <- .Horizontal) {
[Button(.image <- #imageLiteral(resourceName: "Msg_nav1")),
Button(.image <- #imageLiteral(resourceName: "Msg_nav2"), .margin <- Insets(vertical: 0, horizontal: 20)),
Button(.image <- #imageLiteral(resourceName: "Msg_nav3"))]
}]
}
}
self.navigationItem.titleView = titleView
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let element = Grid(.columns <- [.auto, .star(1)], .padding <- Insets(vertical: 8, horizontal: 20)) {
[Image(.width <- 50, .image <- #imageLiteral(resourceName: "Msg_List"), .margin <- Insets(right: 10)),
StackPanel(.gridColumnIndex <- 1) {
[Grid(.columns <- [.star(1), .auto]) {
[Label(.text <- "釘釘運(yùn)動", .fontSize <- 17),
Label(.gridColumnIndex <- 1, .text <- "下午 8:36", .fontSize <- 13, .textColor <- UIColor(white: 0.8, alpha: 1))]
},
Label(.text <- "IT技術(shù)中心 獲得3月24日 XXX有限公司全員步數(shù)第一", .fontSize <- 15, .textColor <- .gray, .margin <- Insets(top: 8))]
}]
}
return tableView.makeCell(element: element)
}
}
Demo已經(jīng)放在https://github.com/huangzhouhong/DeclareLayoutSwift