SwiftUI之深入解析如何創建和組合視圖
一、創建項目并體驗畫布
① 系統要求
創建 SwiftUI 項目工程,體驗畫布、預覽模式和 SwiftUI 模板代碼;
要想在 Xcode 中預覽畫布中的視圖,或者與畫布中的視圖進行交互,需要 Mac 系統版本號不低于 macOS Catalina 10.15。
② 步驟
打開 Xcode,在啟動頁面點擊創建新工程,或者在菜單中選擇文件->新建->項目:
在項目模板選擇器中,選擇 iOS 作為項目平臺,選項單視圖應用(App)作為項目模板,并點擊下一步(Next):
輸入項目名稱 FirstSwiftUI,選擇 SwiftUI 作為用戶界面的創建方式,并點擊下一步 Next,在磁盤目錄下選擇一個位置用來存放新創建的工程項目:
工程創建好并打開后,在文件導航器中,選擇 ContentView.swift 文件,可以瀏覽一下 SwiftUI 視圖的組成結構。默認情況下,SwiftUI 的視圖文件包含兩個結構體 Struct:
第一個結構體遵循 View 協議,描述視圖的內容和布局;
第二個結構體聲明為第一個視圖的預覽視圖。
在**畫布(Canvas)上,點擊恢復(Resume)**按鈕可以顯示預覽視圖,也可以使用快捷鍵 Command+Option+P(如果工程中沒有出現畫布 Canvas,可以選擇菜單:編輯器 Editor -> 編輯器和畫布 Canvas,打開畫布進行預覽):
在 body 屬性內部,修改文字 Hello, world! 為其它的不同的文字,當在改變代碼的同時,預覽視圖也會實時的更新對應的內容變化:
二、定制文本視圖 Text View
① 通過修改代碼來改變視圖的顯示樣式
可以通過修改代碼來改變一個視圖的顯示樣式,也可以通過檢查器獲取視圖可修改屬性,然后再寫對應的代碼改變樣式。在創建應用的過程中,可以同時使用源碼編輯器、畫布或者檢查器,無論當前使用的是哪一個工具編輯視圖,代碼會保持和這些編輯器展示的樣式一致:
② 使用檢查器來定制視圖的顯示樣式
在預覽視圖中,按下 Command 鍵的同時點擊控件,會彈出一個編輯彈層,然后選擇檢查器 Inspect, 編輯彈層顯示所有可以定制的視圖屬性,選中的控件不同,可以定制的屬性集合也不相同:
使用檢查器把文字更改為Turtle Rock,也就是在應用中顯示的第一個地標的名稱:
改變字體修改器為 Title,使用系統字體修飾文字,可以自動按照用戶在設備中設置的字體偏好大小進行調整。定制 SwiftUI 視圖所調用的方法被稱為視圖修改器 Modifiers,修改器在原視圖的基礎上修改部分顯示樣式和屬性,返回一個新的視圖,這樣就可以讓多個修改器串連進行,形成水平方向的鏈式調用,或者垂直方向的堆疊調用:
手動在代碼中添加 foregroundColor(.green) 屬性修改器,就會把文字的顏色調整為綠色。代碼是決定視圖樣式的根本,當我們使用檢查器來改變或移除一個屬性修改器時,Xcode 也會在代碼編輯器中同步改變或移除對應的修改器代碼:
在代碼編輯器中,按下 Command 的同時點擊 Text 單詞也可以屬性彈窗,從中選擇檢查器后,再點擊 Color 彈出菜單,選擇繼承 Inherited,讓文字的顏色恢復成原來的黑色:
當我們移除 foregroundColor(.green) 時,Xcode 會自動更新代碼來反映視圖的實際顯示狀況:
三、使用棧來組合視圖
上文中創建了標題視圖,接下來要添加一些文本視圖來描述地標所在州及所在公園的名稱等其它詳細信息:
創建 SwiftUI 視圖就是在 body 屬性中描述視圖的內容、布局及行為,但 body 屬性只返回單個視圖,這時組合多個視圖時可以把它們放入一個棧中,通過水平、垂直、前后嵌套多個視圖完成視圖組合,做為一個整體在 body 屬性中返回。
現在使用一個垂直棧,把標題放在包含公園詳情的水平棧的上方,在水平棧中,布局公園詳情相關的內容,可以使用 Xcode 提供的結構化布局來把視圖嵌套在容器視圖中。
① 按下 Command 鍵的同時,點擊 Text 視圖的初始化代碼打開結構化編輯彈窗,然后選擇把控件嵌套在垂直棧中 Embed in VStack,在棧中添加 Text View 控件可以從組件中直接拖進棧中完成:
② 點擊 Xcode 右上角的 + 號,托動一個 Text 控件到指定位置,代碼立即就會在編輯器中補全;
③ 把 Text 視圖的占位文本修改為 Joshua Tree Nation Park,視圖會自動調整位置布局;
④ 設置位置控件的字體為子標題樣式:
struct ContentView: View { var body: some View { VStack { Text("Turtle Rock") .font(.title) .padding() Text("Joshua Tree Nation Park") .font(.title2) } } }
1
2
3
4
5
6
7
8
9
10
11
⑤ 設置 VStack 初始化參數為左對齊內部的子視圖,默認情況下,棧會把內部視圖在自己的主軸上居中對齊,并自動計算各子視圖的間距。下一步要添加一個 Text 控制用來描述公園的狀態,它水平排列在位置信息的右邊;
⑥ 在畫布內,command 按下的同時點擊位置視圖,在彈出的菜單中選擇嵌入到水平棧中 Embed in HStack;
⑦ 在位置控件的后面加一個公園狀態的 Text 視圖,并把占位文字改為 California,字體設置為子標題樣式;
⑧ 為了水平布局使用整個屏幕寬度,在位置控件和公園狀態控件中間添加一個 Spacer 控件,用來填充兩個控件中間的空白部分,并把兩個控件分別頂向屏幕的兩側;Spacer 是一個可以伸縮的空白控件,它負責占用其它控件布局完成后剩下的所有空間;
⑨ 使用 padding() 修改器給地標信息內容視圖整體加內邊距;
四、創建自定義圖像視圖 Image
有了地標名稱、地標位置及狀態視圖,下一步再添加一個地標圖片視圖,這個圖片視圖將自定義遮罩 mask、邊框 border 和陰影 shadow;可以從控件加中拖一個 Image 到畫布,或直接寫代碼到代碼編輯器中。
在項目資源文件中找到 turtlerock.png 圖片,把它拖入資源編輯器 asset catalog editor 中,Xcode 會創建一個新的圖片集來存放這個圖片,然后創建一個 SwiftUI 視圖:
選擇文件->新建->文件,打開模板選擇器,在用戶界面(User Interface)板塊下,選擇 SwiftUI View 并點擊下一步,命名為 CircleImage.swift,并點擊創建(Create),現在已經準備好插入圖片并修改布局來滿足設計目標:
用 Image 替換 Text,并使用 turtlerock 圖片初始化 Image 視圖;
添加 clipShape(Circle()) 修改器到 Image,給圖片添加圓形剪切效果;Circle 是一個形狀,它可以被用作遮罩、也可以是圓圈,還可以是圓形填充視圖;
創建另一個灰色的圓圈并把它作為一個浮層添加到圖片上,相當于給圖片加了一個灰色邊框;
給視圖添加半徑為 10 的陰影;
把圓形邊框的顏色改成白色,就完成了自定義圖片視圖的創建:
五、UIKit 視圖與 SwiftUI 視圖混合使用
現在要創建一個地圖視圖,可以使用 MapKit 中的 MKMapView 視圖類來渲染地圖,要在 SwiftUI 中使用 UIView 及其子類,需要把這些 UIView 包裹在一個遵循 UIViewRepresentable 協議的 SwiftUI 視圖中,SwiftUI 中也包含適配 WatchKit 和 AppKit 的類似的協議:
創建一個自定義視圖用來容納和顯示 MKMapView:
選擇文件->新建->文件,選擇 iOS 平臺,選擇 SwiftUI View 模板,并點擊下一步(Next),命名文件為 MapView.swift,并點擊創建(Create);
代碼中導入 MapKit 引用,聲明 MapView 遵循 UIViewRepresentable 協議,UIViewRepresentable 協議要求實現兩個方法 UIView(context:) 和 updateUIView(_:context:),第一個方法用來創建 MKMapView,第二個方法用來配置視圖響應狀態變化;
替換 body,用 makeUIView(context:) 方法來代替,創建并返回一個空的 MKMapView;
創建方法 updateUIView(_:context:),在方法內部設置地圖視圖的坐標為 Turle Rock 的中心。在靜態模式下預覽時,只會渲染 SwiftUI 視圖的部分,因為 MKMapView 是 UIView 的子類,所以需要切換到實時預覽模式下才能看到地圖被完全渲染出來;
點擊 Live Preview(實時預覽)按鈕,可能需要點擊 Try Again 和 Resume 按鈕來激活預覽模式的切換,切換到實時預覽模式下不久就可以看到指定地標所在的地圖位置:
六、組合地標詳情頁
我們已經完成了創建一個地標詳情頁所需要的各種子視圖元素:名稱、地點、圓形圖片以及位置地圖,現在可以把這些視圖元素組合在一起形成地標詳情頁的整個視圖:
在項目工程瀏覽器中選擇 ContentView.swift 文件;
body 屬性中嵌入一個 VStack 視圖,它內部包含另一個 VStack 視圖,內部的 VStack 視圖又包含三個 Text 視圖;
在外層 VStack 的頂部添加自定義的地圖視圖 MapView,并使用 frame(width:height:) 設置視圖大小。當只指定高度時,寬度會自動計算為父視圖的寬度,在這里就是屏幕寬度;
點擊 Live Preview 按鈕進入實時預覽模式,查看地圖渲染情況,在實時預覽模式下可以編輯視圖,最新的改動也可以實時的刷新出來;
在 MapView 后面再添加一個 CircleImage 視圖;
為了讓圖片視圖疊放在地圖視圖的上面,可以設置圖片視圖的垂直偏移量為 -130,圖片視圖的底部內邊距也為 -130,這個效果就是把圖片垂直上移了 130,同時和下面的文字區域留出了 130 的空白分隔區;
在外層 VStack 內部的最下面加上 Spacer,可以讓上面的視圖內容頂到屏幕的上邊;
為了讓地圖的視圖內容顯示在狀態欄的下方,可以給 MapView 添加 edgesIgnoringSafeArea(.top) 修改器,這可
以讓它在布局時忽略頂部的安全區域邊距;
七、總結
在聲明自定義 SwiftUI 視圖時,視圖布局要聲明 body 屬性中;View 協議中要求實現 body 屬性,每一個 SwiftUI 視圖都遵循 View 協議。
有如下代碼布局,那么運行視圖效果是什么樣?
struct ContentView: View { var body: some View { CircleImage() VStack(alignment: .leading) { Text("Turtle Rock") .font(.title) Text("Joshua Tree Nation Park") } } }
1
2
3
4
5
6
7
8
9
10
從 body 屬性中返回三個視圖:
VStack(alignment: .leading) { Text("Turtle Rock") .font(.title) Divider() Text("Joshua Tree Nation Park") }
1
2
3
4
5
6
修改器每次都是返回一個新的對象,所以多個修改器可以通過鏈式調用,配置視圖時,使用修改器的方式如下:
Text("Turtle Rock") .font(.title) .foregroundColor(.purple)
1
2
3
完整示例:SwiftUI 之如何創建和組合視圖。
Xcode 容器
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。