使用SwiftUI的聲明性語(yǔ)法虎韵,創(chuàng)建易稠、修改和組合視圖,以便使用Scrumdinger的應(yīng)用程序來(lái)管理會(huì)議包蓝。通過(guò)將一組視圖排列在一起缩多,創(chuàng)建會(huì)議計(jì)時(shí)器屏幕。隨著您在模塊中的進(jìn)展养晋,您將會(huì)反復(fù)回顧計(jì)時(shí)器屏幕衬吆,以便朝著最終設(shè)計(jì)的目標(biāo)進(jìn)行工作。
按照以下步驟開(kāi)始您的新項(xiàng)目绳泉,或者打開(kāi)已完成的項(xiàng)目逊抡,自行探索其中的代碼。
第1節(jié)
創(chuàng)建項(xiàng)目
在整個(gè)模塊中,通過(guò)創(chuàng)建Scrumdinger應(yīng)用程序冒嫡,您將學(xué)習(xí)應(yīng)用程序開(kāi)發(fā)的基礎(chǔ)知識(shí)拇勃。在向應(yīng)用程序添加新功能的過(guò)程中,您將探索Xcode和SwiftUI的基礎(chǔ)知識(shí)孝凌。在本節(jié)中方咆,您將創(chuàng)建Scrumdinger的Xcode項(xiàng)目。
步驟1
使用iOS App模板創(chuàng)建一個(gè)新項(xiàng)目蟀架。
步驟2
在項(xiàng)目選項(xiàng)中瓣赂,將產(chǎn)品命名為“Scrumdinger”,點(diǎn)擊界面彈出菜單片拍,并選擇SwiftUI煌集。
模板包含了一個(gè)根視圖的起始文件ContentView.swift,以及定義應(yīng)用程序入口點(diǎn)的文件ScrumdingerApp.swift捌省。
提示:
如果您對(duì)Xcode還不熟悉苫纤,請(qǐng)了解主窗口的相關(guān)信息,并了解如何創(chuàng)建一個(gè)項(xiàng)目纲缓。
步驟3
選擇一個(gè)保存項(xiàng)目的位置卷拘。
第2節(jié)
組合視圖
視圖定義了您的用戶(hù)界面的一部分。它們是應(yīng)用程序的構(gòu)建塊祝高。通過(guò)將小而簡(jiǎn)單的視圖組合在一起栗弟,您可以構(gòu)建一個(gè)復(fù)雜的視圖。在本節(jié)中褂策,您將構(gòu)建計(jì)時(shí)器屏幕的標(biāo)題横腿,以顯示會(huì)議的已用時(shí)間和剩余時(shí)間颓屑。
步驟1
打開(kāi)ContentView.swift斤寂。
默認(rèn)的SwiftUI視圖文件聲明了兩個(gè)結(jié)構(gòu)體。第一個(gè)結(jié)構(gòu)體遵循View協(xié)議揪惦,該協(xié)議有一個(gè)要求:一個(gè)返回View的body屬性遍搞。在body屬性中,您描述視圖的內(nèi)容器腋、布局和行為溪猿。第二個(gè)結(jié)構(gòu)體為該視圖定義了一個(gè)預(yù)覽,以在畫(huà)布上顯示纫塌。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
您將對(duì)ContentView.swift進(jìn)行重構(gòu)诊县,以為其指定一個(gè)與您的應(yīng)用程序目的相關(guān)的名稱(chēng)。
步驟2
對(duì)ContentView結(jié)構(gòu)體進(jìn)行控制點(diǎn)擊措左,選擇Refactor > Rename依痊,并將結(jié)構(gòu)體重命名為MeetingView。
您還可以將預(yù)覽結(jié)構(gòu)體重命名為MeetingView_Previews怎披,以保持命名的一致性胸嘁。
步驟3
將現(xiàn)有body的內(nèi)容替換為ProgressView瓶摆,并使用占位數(shù)據(jù)初始化視圖。
當(dāng)您在項(xiàng)目導(dǎo)航器中選擇一個(gè)SwiftUI文件時(shí)性宏,畫(huà)布會(huì)在編輯器旁邊打開(kāi)群井。畫(huà)布會(huì)顯示運(yùn)行時(shí)視圖的預(yù)覽。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
ProgressView(value: 10, total: 15)
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
步驟4
將進(jìn)度視圖的值從10更改為5毫胜,并觀察畫(huà)布中的進(jìn)度視圖更新书斜。
您將使用進(jìn)度視圖來(lái)顯示Scrum期間已經(jīng)過(guò)的時(shí)間的百分比。進(jìn)度視圖還可以顯示不確定的進(jìn)度指蚁,比如當(dāng)應(yīng)用程序正在加載數(shù)據(jù)時(shí)菩佑。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
ProgressView(value: 5, total: 15)
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
步驟5
按住Command鍵點(diǎn)擊ProgressView,然后選擇“Embed in VStack”凝化。
堆棧將視圖水平稍坯、垂直或前后分組。您可以使用堆棧來(lái)組合和層疊視圖組件搓劫。
步驟6
在代碼編輯器中創(chuàng)建一個(gè)HStack瞧哟,點(diǎn)擊庫(kù)按鈕,并將一個(gè)文本視圖拖到HStack中枪向,并設(shè)置值為"Seconds Elapsed"勤揩。
無(wú)論您使用源代碼編輯器、畫(huà)布秘蛔、庫(kù)或檢查器來(lái)修改視圖陨亡,您的代碼都會(huì)保持更新。
步驟7
添加另一個(gè)值為"Seconds Remaining"的文本視圖深员。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
Text("Seconds Elapsed")
Text("Seconds Remaining")
}
}
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
步驟8
將每個(gè)文本視圖嵌套在一個(gè)VStack中负蠕。
步驟9
在第一個(gè)文本視圖下方添加一個(gè)標(biāo)題為"300"、系統(tǒng)圖片為"hourglass.tophalf.fill"的標(biāo)簽倦畅。
該圖像使用了SF Symbols 4中的一個(gè)遮糖。系統(tǒng)將這些符號(hào)視為字體,因此它們會(huì)根據(jù)用戶(hù)設(shè)備的設(shè)置進(jìn)行動(dòng)態(tài)縮放叠赐。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack {
Text("Seconds Elapsed")
Label("300", systemImage: "hourglass.tophalf.fill")
}
VStack {
Text("Seconds Remaining")
}
}
}
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
步驟10
在第二個(gè)文本視圖下方添加一個(gè)標(biāo)題為"600"欲账、系統(tǒng)圖片為"hourglass.bottomhalf.fill"的標(biāo)簽。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack {
Text("Seconds Elapsed")
Label("300", systemImage: "hourglass.tophalf.fill")
}
VStack {
Text("Seconds Remaining")
Label("600", systemImage: "hourglass.bottomhalf.fill")
}
}
}
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
第3節(jié)
修改和樣式化視圖
現(xiàn)在您已經(jīng)在標(biāo)題中創(chuàng)建了基本視圖芭概,您將對(duì)會(huì)議計(jì)時(shí)器屏幕的其余部分進(jìn)行原型設(shè)計(jì)和樣式設(shè)置赛不。您將添加內(nèi)置修飾符來(lái)調(diào)整標(biāo)題的外觀。您還將創(chuàng)建額外的堆棧和視圖罢洲,并開(kāi)始添加控件踢故。
您將通過(guò)調(diào)整視圖的間距來(lái)開(kāi)始樣式化標(biāo)題。
步驟1
在每個(gè)VStack之間添加一個(gè)spacer,以利用包含父視圖中的可用空間畴椰。
步驟2
在包圍“Seconds Elapsed”的VStack中添加前導(dǎo)對(duì)齊臊诊,并在包圍“Seconds Remaining”的VStack中添加尾部對(duì)齊。
這些對(duì)齊方式覆蓋了默認(rèn)的居中對(duì)齊方式斜脂。某些系統(tǒng)使用左對(duì)齊和右對(duì)齊抓艳。SwiftUI使用前導(dǎo)對(duì)齊和尾部對(duì)齊來(lái)簡(jiǎn)化您的應(yīng)用程序的本地化。
提示
您還可以通過(guò)選擇VStack并在屬性檢查器中使用對(duì)齊選項(xiàng)來(lái)設(shè)置對(duì)齊方式帚戳。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack(alignment: .leading) {
Text("Seconds Elapsed")
Label("300", systemImage: "hourglass.tophalf.fill")
}
Spacer()
VStack(alignment: .trailing) {
Text("Seconds Remaining")
Label("600", systemImage: "hourglass.bottomhalf.fill")
}
}
}
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}
步驟3
對(duì)文本視圖添加.font(.caption)修飾符以減小文本的大小玷或。
要自定義SwiftUI視圖,您可以調(diào)用稱(chēng)為修飾符的方法片任。每個(gè)修飾符都返回一個(gè)新的視圖偏友。您可以在單個(gè)視圖上使用多個(gè)修飾符。要鏈?zhǔn)秸{(diào)用修飾符对供,請(qǐng)將它們垂直堆疊位他。
現(xiàn)在標(biāo)題具有適當(dāng)?shù)拈g距,您將為屏幕中央顯示的圓形計(jì)時(shí)器視圖創(chuàng)建一個(gè)占位符产场。
步驟4
添加一個(gè)具有邊框的圓形形狀作為占位符鹅髓。
您將在以后的教程中完善圓形計(jì)時(shí)器視圖的設(shè)計(jì)。
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack(alignment: .leading) {
Text("Seconds Elapsed")
.font(.caption)
Label("300", systemImage: "hourglass.tophalf.fill")
}
Spacer()
VStack(alignment: .trailing) {
Text("Seconds Remaining")
.font(.caption)
Label("600", systemImage: "hourglass.bottomhalf.fill")
}
}
Circle()
.strokeBorder(lineWidth: 24)
HStack {
Text("Speaker 1 of 3")
}
}
}
}
通過(guò)創(chuàng)建頁(yè)腳來(lái)完成會(huì)議計(jì)時(shí)器屏幕的原型設(shè)計(jì)京景。
步驟5
添加一個(gè)包含文本視圖的HStack窿冯,顯示"Speaker 1 of 3"。
步驟6
添加一個(gè)使用forward.fill圖像作為標(biāo)簽的按鈕确徙。
暫時(shí)保留按鈕的操作為空醒串。在以后的教程中,您將使操作將計(jì)時(shí)器環(huán)推進(jìn)到下一個(gè)發(fā)言人鄙皇。
步驟7
在文本和按鈕之間添加一個(gè)spacer芜赌。
步驟8
對(duì)頂層的VStack添加padding,將視圖從邊緣向內(nèi)移動(dòng)育苟。
當(dāng)您省略padding(_:)的參數(shù)時(shí)较鼓,SwiftUI會(huì)選擇適合平臺(tái)和展示上下文的默認(rèn)值椎木。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack(alignment: .leading) {
Text("Seconds Elapsed")
.font(.caption)
Label("300", systemImage: "hourglass.tophalf.fill")
}
Spacer()
VStack(alignment: .trailing) {
Text("Seconds Remaining")
.font(.caption)
Label("600", systemImage: "hourglass.bottomhalf.fill")
}
}
Circle()
.strokeBorder(lineWidth: 24)
HStack {
Text("Speaker 1 of 3")
Spacer()
Button(action: {}) {
Image(systemName: "forward.fill")
}
}
}
.padding()
}
}
第4節(jié)
補(bǔ)充輔助功能數(shù)據(jù)
SwiftUI具有內(nèi)置的輔助功能违柏,因此您可以在很少的額外工作下獲得輔助功能支持。例如香椎,文本視圖中的字符串內(nèi)容會(huì)自動(dòng)對(duì)設(shè)備功能(如VoiceOver)進(jìn)行輔助訪問(wèn)漱竖。但有時(shí),您可能希望補(bǔ)充推斷的數(shù)據(jù)畜伐,以增強(qiáng)用戶(hù)的輔助功能體驗(yàn)馍惹。
步驟1
忽略標(biāo)題欄中HStack的子視圖的推斷輔助功能標(biāo)簽和值。
在接下來(lái)的幾個(gè)步驟中添加補(bǔ)充數(shù)據(jù)可以改進(jìn)輔助功能體驗(yàn)。
步驟2
為HStack添加輔助功能標(biāo)簽万矾,傳遞一個(gè)有意義的標(biāo)簽名稱(chēng)悼吱。
考慮標(biāo)簽和值中是否有足夠的上下文讓用戶(hù)理解元素的目的。在這種情況下良狈,您可以通過(guò)添加一個(gè)標(biāo)簽來(lái)補(bǔ)充數(shù)據(jù)后添,讓VoiceOver用戶(hù)只需聽(tīng)取一個(gè)輸出的標(biāo)簽,顯示最重要的信息薪丁。
步驟3
為剩余時(shí)間添加輔助功能值到HStack遇西。
因?yàn)槟幸夂雎粤俗右晥D的值,所以您需要為HStack添加一個(gè)值严嗜。否則粱檀,SwiftUI會(huì)自動(dòng)推斷子視圖的值。
步驟4
為前進(jìn)按鈕添加輔助功能標(biāo)簽漫玄。
默認(rèn)情況下茄蚯,VoiceOver會(huì)讀取圖像的系統(tǒng)名稱(chēng):forward.fill。當(dāng)您添加輔助功能標(biāo)簽時(shí)睦优,VoiceOver會(huì)先讀取標(biāo)簽文本第队,然后是內(nèi)在的輔助功能特征:“下一個(gè)發(fā)言者。按鈕刨秆〉是”
使用這四個(gè)修飾符,您可以增強(qiáng)用戶(hù)的輔助功能體驗(yàn)衡未。
MeetingView.swift
import SwiftUI
struct MeetingView: View {
var body: some View {
VStack {
ProgressView(value: 5, total: 15)
HStack {
VStack(alignment: .leading) {
Text("Seconds Elapsed")
.font(.caption)
Label("300", systemImage: "hourglass.tophalf.fill")
}
Spacer()
VStack(alignment: .trailing) {
Text("Seconds Remaining")
.font(.caption)
Label("600", systemImage: "hourglass.bottomhalf.fill")
}
}
.accessibilityElement(children: .ignore)
.accessibilityLabel("Time remaining")
.accessibilityValue("10 minutes")
Circle()
.strokeBorder(lineWidth: 24)
HStack {
Text("Speaker 1 of 3")
Spacer()
Button(action: {}) {
Image(systemName: "forward.fill")
}
.accessibilityLabel("Next speaker")
}
}
.padding()
}
}
struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
MeetingView()
}
}