importUIKit// 導(dǎo)入 UIKit 為下面布局所用
importPlaygroundSupport// 導(dǎo)入 Playground 運(yùn)行支持的庫(kù)
// 我將會(huì)采用一種非常簡(jiǎn)潔的方式來(lái)添加界面元素、完成布局、配置界面屬性但是不會(huì)用到 `Storybards`.
classOurAwesomeViewController:UIViewController{
// 在這里的所有UI元素, 我都會(huì)用 懶加載 方式來(lái)初始化
// 所謂懶加載也就說(shuō)参歹,只有在這些UI元素被添加到界面層級(jí)中去的時(shí)候壁查,才會(huì)調(diào)用他們的內(nèi)聯(lián)構(gòu)造函數(shù)進(jìn)行初始化并且只會(huì)調(diào)用一次
// 理想情況下哆窿,我在這里想采用 lazy let 來(lái)強(qiáng)制保證這些UI元素在顯示之后不會(huì)改變拴还,但是 Swift 3 并不支持
// 那如果我們直接用 let 又如何呢,答案是也不行贺拣,因?yàn)槿绻@樣的話是無(wú)法在一個(gè)方法中訪問(wèn)到 self 的靖榕,這個(gè)時(shí)候 self 還沒(méi)有初始化完成
lazyvartitleLabel:UILabel= {
// 初始化 label
letlabel =UILabel()
// 將下面的屬性禁止掉标锄,否則會(huì)有很多布局的錯(cuò)誤日志輸出.
// 我也不清楚為什么默認(rèn)值是 "true",反正現(xiàn)在用不到它了.
label.translatesAutoresizingMaskIntoConstraints =false
// 給 label 設(shè)置字體
label.font =UIFont(name:"Menlo", size:14)
// 設(shè)置字體顏色(注意茁计,這里我們不會(huì)牽扯到設(shè)計(jì)的東西)
label.textColor = .white
// 當(dāng)然也可以設(shè)置 label 的顯示內(nèi)容
label.text ="Awesome"
// 讓文字內(nèi)容居中
label.textAlignment = .center
returnlabel
}()
// Button 設(shè)置也大同小異
lazyvarbutton:UIButton= {
// 初始化
letbutton =UIButton()
// 禁用掉這個(gè)多余的屬性
button.translatesAutoresizingMaskIntoConstraints =false
// 設(shè)置按鈕的標(biāo)題內(nèi)容
button.setTitle("Press Me",for: .normal)
// 給按鈕綁定事件函數(shù)
button.addTarget(self,
action: #selector(OurAwesomeViewController.buttonTest),
for: .touchUpInside)
returnbutton
}()
// 在這里添加布局代碼料皇,當(dāng)界面準(zhǔn)備顯示在屏幕上的時(shí)候這個(gè)方法就會(huì)在 UIKit 中被調(diào)用
overridefuncloadView(){
// 如果要采用UIKit默認(rèn)提供的view,請(qǐng)別忘了調(diào)用 super 的 loadView 方法,如果不用的話,也要給self.view賦值
super.loadView()
// 自定義 view 的背景色
view.backgroundColor = .blue
// StackView 控件會(huì)節(jié)省很多時(shí)間. 它會(huì)自動(dòng)管理子界面的布局方式并且可以結(jié)合一些屬性設(shè)置就可以避免臃余的界面約束
// StackView 控件還可以嵌套甚至設(shè)置一些邊距以滿足各種復(fù)雜的布局情況.在我看來(lái),這種布局方式要比設(shè)置約束簡(jiǎn)單有效的多.
letverticalLayout =UIStackView(arrangedSubviews: [titleLabel, button])
// 同樣的禁用掉這個(gè)屬性
verticalLayout.translatesAutoresizingMaskIntoConstraints =false
// 設(shè)置垂直方向布局践剂,并且設(shè)置填充和對(duì)齊方式.
// 這里不用記到底用了哪個(gè)屬性鬼譬,只要大體有個(gè)印象,用的時(shí)候查下也可以了.
verticalLayout.axis = .vertical
verticalLayout.alignment = .fill
verticalLayout.distribution = .fill
// 如果你要設(shè)置一些邊距逊脯,可以像下面這樣做
verticalLayout.isLayoutMarginsRelativeArrangement =true
verticalLayout.layoutMargins =UIEdgeInsets(top:20,left:20, bottom:20,right:20)
// 我們給 StackView 控件設(shè)置一些布局約束來(lái)矯正它的位置
// 這部分代碼可以抽象一下寫(xiě)成一個(gè)類庫(kù)來(lái)簡(jiǎn)化代碼.在下面文章中我會(huì)展示出來(lái)
lettopConstraint =NSLayoutConstraint(item: verticalLayout,
attribute: .top,
relatedBy: .equal,
toItem: view,
attribute: .top,
multiplier:1,
constant:0)
letbottomConstraint =NSLayoutConstraint(item: verticalLayout,
attribute: .bottom,
relatedBy: .equal,
toItem: view,
attribute: .bottom,
multiplier:1,
constant:0)
letleftConstraint =NSLayoutConstraint(item: verticalLayout,
attribute: .left,
relatedBy: .equal,
toItem: view,
attribute: .left,
multiplier:1,
constant:0)
letrightConstraint =NSLayoutConstraint(item: verticalLayout,
attribute: .right,
relatedBy: .equal,
toItem: view,
attribute: .right,
multiplier:1,
constant:0)
// 現(xiàn)在添加到view中...
view.addSubview(verticalLayout)
// 添加上面的約束.
view.addConstraints([topConstraint, bottomConstraint, leftConstraint, rightConstraint])
}
// 當(dāng)按鈕被點(diǎn)擊時(shí)优质,這個(gè)測(cè)試方法會(huì)被調(diào)用.
funcbuttonTest(sender: UIButton){
// 這里只是改變了界面的顏色
view.backgroundColor = .red
}
}
// 將上面的 view controller 綁定到 playground 上.
PlaygroundPage.current.liveView =OurAwesomeViewController()
PlaygroundPage.current.needsIndefiniteExecution =true
// 用純手工的方式編寫(xiě)布局代碼可能看起來(lái)有點(diǎn)費(fèi)力,但這樣做對(duì)于了解UI元素的布局原理军洼,位置分布巩螃,屬性設(shè)置是非常有用的.
// 采用這種方式更容易用 git 來(lái)跟蹤歷史變化, 所以在某些方面我個(gè)人認(rèn)為要比 Interface Builder 更簡(jiǎn)單易用一些.
// 附加內(nèi)容!!!
// 你可能會(huì)想把以上代碼用到真是的 Xcode 工程中去,而不是僅僅在 Playgrounds 里面跑跑.
// 首先匕争,當(dāng)你創(chuàng)建完工程之后避乏,在工程文件里一般會(huì)有一個(gè) `Main Interface` 的配置,它通常是第一個(gè)要加載的 `Storyboard`.
// 現(xiàn)在我們不用它了汗捡,可以把它刪掉.
// 下一步
// 在 AppDelegate 的 applicationDidFinishLaunchingWithOptions 中淑际,只需要改變一行代碼即可.
classAppDelegate:UIResponder,UIApplicationDelegate{
varwindow:UIWindow?
funcapplication(_application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? =nil)->Bool{
window =UIWindow(frame:UIScreen.main.bounds)
window?.rootViewController =OurAwesomeViewController()
window?.makeKeyAndVisible()
returntrue
}
}