文章內(nèi)容源處:
https://juejin.im/post/5cf5f4596fb9a07ede0b2fa1#heading-34
SwiftUI基礎(chǔ)教程
SwiftUI只支持Xcode 11、iOS 13版本及以上宫仗。
官方文檔鏈接:developer.apple.com/tutorials/s…
創(chuàng)建組合視圖
本篇文章將通過(guò)一個(gè)構(gòu)建應(yīng)用(Landmarks,一個(gè)可以發(fā)現(xiàn)子巾、分享你喜歡地點(diǎn)的App)示例,來(lái)引導(dǎo)大家進(jìn)行SwiftUI開(kāi)發(fā)小压。我們將使用SwiftUI框架來(lái)構(gòu)建Landmark詳情界面线梗。
Landmarks利用stacks將圖片和文本組合起來(lái)來(lái)進(jìn)行視圖布局。你需要引用MapKit框架頭文件來(lái)創(chuàng)建一個(gè)地圖視圖怠益。 你可以通過(guò)Xcode新的實(shí)時(shí)反饋功能仪搔,來(lái)優(yōu)化你的視圖布局。
1.下載Demo工程蜻牢。
2.下載Xcode11 Beta烤咧。
創(chuàng)建工程
利用SwiftUI應(yīng)用模版來(lái)創(chuàng)建工程,然后探索了解下SwiftUI的畫(huà)布抢呆。
為了能夠體驗(yàn)Xcode 11的view實(shí)時(shí)預(yù)覽和交互功能煮嫌,一定要確保你的mac系統(tǒng)版本是macOS 10.15 beta。
第一步
打開(kāi) Xcode->Create a new Xcode project抱虐,或者通過(guò)File > New > Project來(lái)創(chuàng)建工程昌阿。
第二步
在模版選擇區(qū)域,選擇 iOS->Single View App->Next恳邀。
第三步
輸入項(xiàng)目名稱 Landmarks->勾選Use SwiftUI->Next保存懦冰。
第四步
在Xcode導(dǎo)航欄,創(chuàng)建ContentView.swift谣沸。通常SwiftUI會(huì)聲明兩個(gè)結(jié)構(gòu)體刷钢。第一個(gè)結(jié)構(gòu)體繼承自View,并且在這兒進(jìn)行View的布局乳附。第二個(gè)結(jié)構(gòu)體聲明了一個(gè)ContentView 的preview,繼承自PreviewProvider内地。
感謝@SoolyChristina基友的友情提示。這兒并非是繼承的概念赋除,原文的描述如下: The first structure conforms to the View protocol and describes the view’s content and layout. The second structure declares a preview for that view.
所以這兒聲明的兩個(gè)結(jié)構(gòu)體阱缓,更像是遵循了View和PreviewProvider協(xié)議。
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
第五步
在SwiftUI畫(huà)布中點(diǎn)擊 Resume進(jìn)行視圖預(yù)覽贤重。
Tip:如果畫(huà)布沒(méi)有展示出來(lái)茬祷,可以通過(guò) Editor > Editor and Canvas顯示出來(lái)。
第六步
把Hello World更改為Hello SwiftUI!
當(dāng)你修改文案后并蝗,SwiftUI會(huì)自動(dòng)更新視圖祭犯。(這他么不就是熱重載嘛 Hot-Reload)
自定義Text View
你有兩種方式來(lái)自定義TextView。第一種方式是直接修改view代碼滚停,第二種方式是通過(guò)inspector檢查器來(lái)幫助你進(jìn)行代碼編寫(xiě)沃粗。
當(dāng)你構(gòu)建Landmarks的時(shí)候,你可以運(yùn)用任何一個(gè)編輯器來(lái)進(jìn)行編碼工作:直接修改源代碼键畴、通過(guò)畫(huà)布最盅、通過(guò)inspector view檢查器。代碼并不會(huì)關(guān)心你用什么工具起惕,它始終能夠保持最新?tīng)顟B(tài)涡贱。
接下來(lái),你將通過(guò)inspector來(lái)自定義Text View
第一步
在preview畫(huà)布上惹想,按住Command鍵+點(diǎn)按Text文本框问词,這時(shí)候inspector就會(huì)被喚起。
inspector彈出框所展示的屬性也會(huì)因?yàn)椴煌腢I控件而有所不同嘀粱。
第二步
通過(guò)inspector檢查器修改Text文本框的屬性激挪。
第三步
修改文本框字體。
修改文本框字體是利用的系統(tǒng)的字體锋叨。
第四步
手動(dòng)修改代碼垄分,即添加.color(.green) 把文本修改成綠色。
要自定義SwiftUI視圖娃磺,你可以調(diào)用modifiers方法薄湿。Modifiers可以修改視圖的屬性,并且modifier返回一個(gè)新的視圖偷卧,所以通常會(huì)將多個(gè)modifiers像鏈一樣垂直堆疊在一起嘿般。( 說(shuō)白了就是鏈?zhǔn)骄幊蹋空{(diào)用一個(gè)方法就返回自身)涯冠。
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Turtle Rock")
.font(.title)
.color(.green)
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
你編寫(xiě)的代碼肯定和view是一一對(duì)應(yīng)的炉奴。當(dāng)你通過(guò)inspector修改了view屬性之后,Xcode會(huì)自動(dòng)更新你的代碼蛇更。
第五步
這時(shí)候瞻赶,打開(kāi)inspector,然后把文本Color屬性修改為Inherited派任。
第六步
注意一點(diǎn)的就是砸逊,Xcode會(huì)根據(jù)inspector修改自動(dòng)更新你的代碼。
利用Stacks組合視圖
我們創(chuàng)建了一個(gè)文本框用來(lái)顯示landmark的詳情信息掌逛,并且把這個(gè)文本控件放到頭部师逸。
當(dāng)我們創(chuàng)建SwiftUI視圖控件的時(shí)候,我們會(huì)把控件的內(nèi)容、布局還有一些行為放在body屬性中念祭;然而body屬性只返回了一個(gè)view霉咨。你可以利用stacks嵌入多個(gè)view黄锤,它可以垂直嵌入雁芙、水平嵌入等厘惦。
在這個(gè)篇幅疟丙,我們將使用垂直stack來(lái)顯示park詳情信息嵌巷。
第一步
Command+點(diǎn)按text初始化方法區(qū)域奠滑。選擇 Embed in VStack丹皱。
第二步
接下來(lái),我們將拖拽一個(gè)text view到stack中宋税。
點(diǎn)擊+號(hào)摊崭,打開(kāi)Library面板。拖拽一個(gè)text view到 “Turtle Rock”后面杰赛。
第三步
修改text view文案為 Joshua Tree National Park呢簸。
第四步
設(shè)置text view的字體。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("Turtle Rock")
.font(.title)
Text("Joshua Tree National Park")
.font(.subheadline)
}
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
第五步
修改VStack對(duì)齊方式淆攻。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
Text("Joshua Tree National Park")
.font(.subheadline)
}
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
如果不設(shè)置對(duì)齊方式阔墩,VStack默認(rèn)是內(nèi)容垂直居中。
第六步
在面板中瓶珊,Command+點(diǎn)按 Joshua Tree National Park喚起inspector啸箫,選擇 Embed in HStack。
第七步
在location后面添加一個(gè)新的文本框伞芹,修改文本框文案并設(shè)置字體忘苛。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack {
Text("Joshua Tree National Park")
.font(.subheadline)
Text("California")
.font(.subheadline)
}
}
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
第八步
可以在兩個(gè)水平的文本框之間添加Space來(lái)適應(yīng)寬度。
Space把父視圖在水平或者垂直方向上全部充滿唱较。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
第九步
最后扎唾,利用padding()來(lái)設(shè)置邊距。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
復(fù)制代碼
創(chuàng)建一個(gè)自定義的圖片視圖
我們已經(jīng)把park名稱和位置的視圖做好了南缓,接下來(lái)我們將給park添加個(gè)圖片胸遇。
你不需要添加很多代碼,就可以添加一個(gè)帶mask汉形、border纸镊、shadow的圖片。
第一步
添加一張圖片到asset catalog中概疆。
在Resource文件夾中找到turtlerock.png圖片逗威,然后把它拖拽到asset catalog中。
第二步
選擇 File > New > File打開(kāi)模版選擇面板岔冀。在 User Interface區(qū)域凯旭,選擇 SwiftUI View->Next,命名為CircleImage.swift。
第三步
把Text構(gòu)建方法替換成Image罐呼。
import SwiftUI
struct CircleImage: View {
var body: some View {
Image("turtlerock")
}
}
struct CircleImage_Preview: PreviewProvider {
static var previews: some View {
CircleImage()
}
}
復(fù)制代碼
第四步
調(diào)用.clipShape(Circle())方法鞠柄,創(chuàng)建圓形視圖。
第五步
再創(chuàng)建一個(gè)圓圈弄贿,用灰色進(jìn)行填充春锋。并將它作為image的border矫膨。
import SwiftUI
struct CircleImage: View {
var body: some View {
Image("turtlerock")
.clipShape(Circle())
.overlay(
Circle().stroke(Color.gray, lineWidth: 4))
}
}
struct CircleImage_Preview: PreviewProvider {
static var previews: some View {
CircleImage()
}
}
復(fù)制代碼
第六步
添加陰影差凹。
第七步
將邊框顏色更改為白色。
import SwiftUI
struct CircleImage: View {
var body: some View {
Image("turtlerock")
.clipShape(Circle())
.overlay(
Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
}
}
struct CircleImage_Preview: PreviewProvider {
static var previews: some View {
CircleImage()
}
}
復(fù)制代碼
UIKit和SwiftUI混合使用
現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)地圖視圖侧馅。你可以MapKit中的MKMapView類(lèi)來(lái)展示渲染地圖界面危尿。
在SwiftUI中要使用UIView或者其子類(lèi),你需要讓你的view遵循UIViewRepresentable協(xié)議馁痴。SwiftUI在WatchKit和AppKit同樣聲明了類(lèi)似的協(xié)議谊娇。
第一步
創(chuàng)建新的SwiftUI View來(lái)展示MKMapView。 File > New > File罗晕,然后創(chuàng)建MapView.swift济欢。
第二步
引入MapKit頭文件,并且讓MapView遵循UIViewRepresentable協(xié)議小渊。
第三步
UIViewRepresentable協(xié)議有兩個(gè)協(xié)議方法需要實(shí)現(xiàn)法褥。第一是UIView(context:)來(lái)創(chuàng)建MKMapView。第二個(gè)updateUIView(_:context:)來(lái)更新view酬屉。
把body屬性干掉半等,然后UIView(context:)協(xié)議方法來(lái)創(chuàng)建MKMapView。
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
}
struct MapView_Preview: PreviewProvider {
static var previews: some View {
MapView()
}
}
復(fù)制代碼
第四步
實(shí)現(xiàn)updateUIView(_:context:)協(xié)議方法呐萨,來(lái)更新view(設(shè)置地圖經(jīng)緯度等)杀饵。
func updateUIView(_ view: MKMapView, context: Context) {
let coordinate = CLLocationCoordinate2D(
latitude: 34.011286, longitude: -116.166868)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
復(fù)制代碼
第五步
當(dāng)在靜態(tài)模式下進(jìn)行預(yù)覽的時(shí)候,Xcode只能渲染SwiftUI視圖控件谬擦。因?yàn)镸KMapView是UIView子類(lèi)切距,所以你需要把模式切換成live模式才能正常預(yù)覽。
點(diǎn)擊 Live Preview切換預(yù)覽模式惨远。
把上面的子控件組合成一個(gè)完成的詳情界面
現(xiàn)在我們已經(jīng)把所有子控件定義實(shí)現(xiàn)好了谜悟。
利用我們現(xiàn)有的工具,我們可以把這些子控件組合起來(lái)锨络,形成完整的landmarks詳情界面赌躺。
第一步
在工程導(dǎo)航區(qū),選擇ContentView.swift文件羡儿。
第二步
在這三個(gè)text view控件外面礼患,再嵌入一個(gè)VStack視圖。
struct ContentView: View {
var body: some View {
VStack {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack(alignment: .top) {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
}
}
}
復(fù)制代碼
第三步
將你自定義的MapView放在stack的上面。設(shè)置MapView的frame缅叠。
如果你只設(shè)置了Mapview的高度悄泥,那么MapView會(huì)自動(dòng)設(shè)置其寬度來(lái)適應(yīng)父視圖。所以MapView會(huì)充滿寬度區(qū)域肤粱。
struct ContentView: View {
var body: some View {
VStack {
MapView()
.frame(height: 300)
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack(alignment: .top) {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
}
}
}
復(fù)制代碼
第四步
點(diǎn)擊 Live Preview來(lái)預(yù)覽效果弹囚。
預(yù)覽狀態(tài)下,你可以繼續(xù)編寫(xiě)view的代碼领曼,Live Preview會(huì)實(shí)時(shí)更新視圖鸥鹉。
第五步
將CircleImage添加到stack上面。
struct ContentView: View {
var body: some View {
VStack {
MapView()
.frame(height: 300)
CircleImage()
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack(alignment: .top) {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
}
}
}
復(fù)制代碼
第六步
調(diào)整一下Image的偏移庶骄。
第七步
在VStack的底部添加spacer占位毁渗。
第八步
最后設(shè)置下 edgesIgnoringSafeArea(.top) 。
作者:一線搬磚工人
鏈接:https://juejin.im/post/5cf5f4596fb9a07ede0b2fa1
來(lái)源:掘金
著作權(quán)歸作者所有单刁。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)灸异,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。