天津視頻網(wǎng)站開發(fā)團(tuán)隊(duì)今日新聞國內(nèi)大事件
安全域視圖
SwiftUI還內(nèi)置了創(chuàng)建安全文本框的視圖。這一視圖會把用戶輸入的字符替換成點(diǎn)以及隱藏敏感信息,比如密碼。
- SecureField(String, text: Binding):該初始化方法創(chuàng)建一個(gè)安全輸入框。第一個(gè)參數(shù)定義占位文本,?
?text?
?參數(shù)為存儲用戶插入值的綁定屬性。
實(shí)現(xiàn)方式與??TextField?
?視圖相同,我們也可以應(yīng)用相同的修飾符,如下所示。
示例6-29:使用安全文本框
struct ContentView: View {@State private var pass: String = ""var body: some View {VStack(spacing: 15) {Text(pass).padding()SecureField("Insert Password", text: $pass).textFieldStyle(.roundedBorder)Spacer()}.padding()}
}
??SecureField?
??視圖和??TextField?
?視圖外觀一樣。唯一的差別是其中的字符是隱藏的。
圖6-15:安全文本框
??跟我一起做:創(chuàng)建一個(gè)多平臺項(xiàng)目。使用示例6-29中的代碼更新??ContentView?
?視圖。在輸入框中插入字符。會看到字符被替換成為小黑點(diǎn),如圖6-15所示。
文本編輯器視圖
SwiftUI還自帶一個(gè)稱為??TextEditor?
?的視圖讓用戶可以插入多行文本。以下是該視圖的初始化方法。
- TextEditor(text: Binding):此初始化方法創(chuàng)建一個(gè)文本編輯器。?
?text?
?參數(shù)是存儲用戶所插入文本的綁定屬性。
該視圖可以接收前面用于格式化文本的??TextField?
??和??Text?
?視圖的一些修飾符。例如,我們可以設(shè)置視圖中文本的對齊、行間距以及是否做錯誤檢查。
示例6-30:實(shí)現(xiàn)一個(gè)文本編輯器
struct ContentView: View {@State private var text: String = ""var body: some View {TextEditor(text: $text).multilineTextAlignment(.leading).lineSpacing(10).autocorrectionDisabled(true).padding(8)}
}
圖6-16:文本編輯器
開關(guān)視圖
??Toggle?
?視圖創(chuàng)建一個(gè)在兩種狀態(tài)間切換的控件。默認(rèn)在移動設(shè)備上顯示為對用戶友好的開關(guān),在Mac上顯示為復(fù)選框。該視圖包含如下初始化方法。
- Toggle(String, isOn: Binding):該初始化方法創(chuàng)建一個(gè)?
?Toggle?
??視圖。第一個(gè)參數(shù)定義標(biāo)簽,??isOn?
?參數(shù)為存儲當(dāng)前狀態(tài)的綁定屬性。本視圖還自帶有一個(gè)由閉包返回視圖的標(biāo)簽(Toggle(isOn: Binding, label: Closure))。
該視圖要求綁定屬性存儲當(dāng)前值。在下例中,我們提供了一個(gè)??@State?
?屬性并使用屬性值來選取適當(dāng)?shù)臉?biāo)簽。
示例6-31:實(shí)現(xiàn)一個(gè)開關(guān)
struct ContentView: View {@State private var currentState: Bool = truevar body: some View {VStack {Toggle(isOn: $currentState, label: {Text(currentState ? "On" : "Off")})Spacer()}.padding()}
}
示例6-31中的代碼使用三元運(yùn)算符來檢測??currentState?
??屬性的值并顯示相應(yīng)的文本(On或Off)。默認(rèn)我們設(shè)置屬性值為??true?
?,因此開關(guān)處于打開狀態(tài)并在屏幕上顯示On標(biāo)簽,但如果點(diǎn)擊開關(guān),就會關(guān)閉,視圖更新為顯示Off標(biāo)簽。
圖6-17:打開和關(guān)閉開關(guān)
??跟我一起做:創(chuàng)建一個(gè)多平臺項(xiàng)目。使用示例6-31中的代碼更新??ContentView?
?視圖。點(diǎn)擊打開或關(guān)閉開關(guān)。使用這個(gè)項(xiàng)目測試下面的例子。
賦值給??label?
?參數(shù)的閉包可以包含另外一個(gè)定義副標(biāo)題的視圖,如下例所示。
示例6-32:添加副標(biāo)題
struct ContentView: View {@State private var currentState: Bool = truevar body: some View {VStack {Toggle(isOn: $currentState, label: {Text(currentState ? "On" : "Off")Text("Enable or Disable")})Spacer()}.padding()}
}
圖6-18:帶標(biāo)題和副標(biāo)題的開關(guān)
??Toggle?
??視圖創(chuàng)建了一個(gè)包含標(biāo)題和控件中間為彈性空間的橫向布局,結(jié)果就是整個(gè)視圖占滿容器的橫向空間,標(biāo)簽和控件位于兩端。如果希望對視圖的位置和尺寸做精確控制,可以應(yīng)用此前介紹過的??fixedSize?
?修飾符來降低視圖的尺寸,或使用如下修飾符隱藏標(biāo)簽。
- labelsHidden():此修飾符隱藏賦值給控件的標(biāo)簽。
這一修飾符適用于多款控件,但對開關(guān)尤為有用。下例展示了如何實(shí)現(xiàn)它來為控件定義一個(gè)自定義標(biāo)簽。
示例6-33:為??Toggle?
?視圖定義一個(gè)自定義標(biāo)簽
struct ContentView: View {@State private var currentState: Bool = truevar body: some View {HStack {Toggle("", isOn: $currentState).labelsHidden()Text(currentState ? "On" : "Off").padding().background(Color(currentState ? .yellow : .gray))}.padding()}
}
視圖現(xiàn)在為控件的大小并在屏幕中心顯示。標(biāo)簽不再顯示 ,因此我們將其聲明為空字符串,但在當(dāng)前值的側(cè)邊包含一個(gè)??Text?
?視圖。
圖6-19:自定義大小以及開關(guān)的標(biāo)簽
類似??Button?
??視圖,??Toggle?
?視圖也實(shí)現(xiàn)了修飾符用于定義控件的樣式。
- toggleStyle(ToggleStyle):這一修飾符定義開關(guān)的樣式。參數(shù)是一個(gè)遵循?
?ToggleStyle?
??協(xié)議的結(jié)構(gòu)體。為創(chuàng)建標(biāo)準(zhǔn)的結(jié)構(gòu)體,框架包含了??automatic?
??、??button?
??、??checkbox?
??和??switch?
?這些屬性。
默認(rèn)值為??automatic?
??,表示控件的樣式由系統(tǒng)選擇。如果希望保持同一種樣式,可以賦值??switch?
??或??checkbox?
??(僅能用于Mac)。這些值用于指定標(biāo)準(zhǔn)樣式,但框架還內(nèi)置了??button?
?值來創(chuàng)建完全不同類型的控件。在將這一樣式賦值給視圖時(shí),系統(tǒng)顯示一個(gè)開關(guān)按鈕來表示開和關(guān)的狀態(tài)。在按鈕處于開的狀態(tài)時(shí),高亮顯示,否則顯示 為標(biāo)準(zhǔn)按鈕。
示例6-34:實(shí)現(xiàn)一個(gè)開關(guān)按鈕
struct ContentView: View {@State private var currentState: Bool = truevar body: some View {HStack {Toggle(isOn: $currentState, label: {Label("Send", systemImage: "mail")}).toggleStyle(.button)}.padding()}
}
圖6-20:切換按鈕為開關(guān)狀態(tài)
框架提供的樣式是有限的,但我們可以自行創(chuàng)建。只需要定義一個(gè)遵循??ToggleStyle?
?協(xié)議的結(jié)構(gòu)體。該協(xié)議要求結(jié)構(gòu)體實(shí)現(xiàn)如下方法。
- makeBody(configuration: Configuration):該方法定義并返回一個(gè)替換開關(guān)主體的視圖。?
?configuration?
??參數(shù)是一個(gè)??Configuration?
?類型的值,包含控件相關(guān)信息。
這個(gè)方法接收一個(gè)類型為??Configuration?
??的值,是??ToggleStyleConfiguration?
?的類型別名,包含如下屬性來返回控件相關(guān)的信息。
- isOn:該屬性返回一個(gè)表示開關(guān)處于開或關(guān)狀態(tài)的布爾值。
- label:該屬性返回定義開關(guān)標(biāo)簽的視圖。
??isOn?
??是一個(gè)綁定屬性,創(chuàng)建與視圖的雙向綁定,因此我們可以讀取并修改其值來激活或停用控件。在下例中,我們創(chuàng)建了一個(gè)類似復(fù)選框的??Toggle?
?視圖。點(diǎn)擊控件時(shí),圖形變換顏色來表示當(dāng)前的狀態(tài)(灰色為停用,綠色為激活)。
示例6-35:定義一個(gè)自定義??Toggle?
?視圖
struct MyStyle: ToggleStyle {func makeBody(configuration: Configuration) -> some View {HStack(alignment: .center) {configuration.labelSpacer()Image(systemName: "checkmark.rectangle.fill").font(.largeTitle).foregroundColor(configuration.isOn ? Color.green : Color.gray).onTapGesture {configuration.$isOn.wrappedValue.toggle()}}}
}struct ContentView: View {@State private var currentState: Bool = falsevar body: some View {VStack {HStack {Toggle("Enabled", isOn: $currentState).toggleStyle(MyStyle())Spacer()}.padding()}}
}
在自定義??Toggle?
??視圖前必須要考慮幾件事。首先,??Configuration?
??結(jié)構(gòu)體的??label?
??屬性包含一個(gè)控件當(dāng)前標(biāo)簽的視圖副本,因此如果想要保留這個(gè)標(biāo)簽,必須在新的內(nèi)容中包含這個(gè)值。第二,??Toggle?
??視圖使用??HStack?
??視圖和標(biāo)簽與控件間的??Spacer?
??視圖來設(shè)計(jì)。如果想要保留標(biāo)準(zhǔn)設(shè)計(jì),必須保持這種布局。第三,我們負(fù)責(zé)響應(yīng)用戶的交互以及更新控件的狀態(tài),因此必須檢測手勢并在用戶執(zhí)行手勢時(shí)通過修改??isOn?
?屬性的值來變更控件狀態(tài)。
在示例6-35中,我們定義了一個(gè)結(jié)構(gòu)體??MyStyle?
??并實(shí)現(xiàn)了所要求的??makeBody()?
??方法來為??Toggle?
??視圖提供新設(shè)計(jì)。為保留標(biāo)準(zhǔn)樣式,我們使用??HStack?
??視圖來包裝視圖并使用??Spacer?
??視圖來分隔標(biāo)簽與控件。首先我們讀取??label?
??屬性的值來添加當(dāng)前標(biāo)簽,然后聲明??Spacer?
??視圖,最后聲明一個(gè)??Image?
??視圖來展示外觀像復(fù)選框的SF圖標(biāo)。為將??Image?
??視圖轉(zhuǎn)換為控件,我們使用??font()?
??修飾符定義其大小,應(yīng)用??foregroundColor()?
??修飾符來根據(jù)??isOn?
??屬性的當(dāng)前值來修改圖標(biāo)的顏色,最后,使用??onTapGesture()?
??修飾符監(jiān)測用戶何時(shí)點(diǎn)擊??Image?
??視圖。我們會在??第12章???中學(xué)習(xí)更多有關(guān)手勢修飾符的知識?,F(xiàn)在,只需要知道這一修飾符在每次用戶點(diǎn)擊視圖時(shí)執(zhí)行一個(gè)閉包。在這個(gè)閉包中,我們訪問??isOn?
??屬性的綁定值并通過對??wrappedValue?
??屬性中的布爾值應(yīng)用??toggle()?
??修飾符切換值。(本例中,綁定值的setter是私有的,因此通過??wrappedValue?
?屬性訪問它,本章前面做過講解。)這會修改該屬性的當(dāng)前值,進(jìn)而改變控件的狀態(tài),將其打開及關(guān)閉。
圖6-21:??Toggle?
?視圖的自定義樣式
滑塊視圖
??Slider?
?視圖創(chuàng)建一個(gè)控件,允許用戶選擇一個(gè)范圍內(nèi)的值。顯示為一個(gè)帶結(jié)點(diǎn)的橫條,結(jié)點(diǎn)對應(yīng)所選擇的值。該結(jié)構(gòu)體包含如下初始化方法。
- Slider(value: Binding, in: Range, step: Float, onEditingChanged: Closure):這個(gè)初始化方法創(chuàng)建一個(gè)?
?Slider?
?視圖。??value?
?參數(shù)是希望用于存儲當(dāng)前值的綁定屬性,??in?
?參數(shù)是指定用戶選擇的最大、最小值范圍,??step?
?參數(shù)表示當(dāng)前值遞增或遞減的量,??onEditingChanged?
?參數(shù)是在用戶開始或結(jié)束移動滑塊時(shí)執(zhí)行的閉包。
要創(chuàng)建滑動,必須至少提供一個(gè)??@State?
?屬性來存儲值以及一個(gè)決定允許最小和最值的范圍。
示例6-36:創(chuàng)建滑塊
struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {Text("Current Value: \(currentValue.formatted(.number.precision(.fractionLength(0))))")Slider(value: $currentValue, in: 0...10, step: 1.0)Spacer()}.padding()}
}
示例6-36中的代碼創(chuàng)建一個(gè)0到10的滑塊,以??Text?
?視圖顯示當(dāng)前值。??Slider?
?視圖接收類型為??Float?
?和??Double?
?類型的值,因此允許我們選擇浮點(diǎn)值,但我們可以通過聲明??step?
?參數(shù)值為1.0來指定希望用戶選擇的是整數(shù),如本例所示。(注意我們需要使用第4章中介紹的??formatted()?
?方法將??Text?
?視圖的值格式化為整數(shù)。)因?yàn)??currentValue?
?屬性使用數(shù)字5進(jìn)行了初始化,結(jié)點(diǎn)的初始位置就位于正中間。
圖6-22:整數(shù)值滑塊
??Slider?
?初始化方法還內(nèi)置了??onEdittingChanged?
?參數(shù),接收一個(gè)閉包,閉包接收表示用戶開始或結(jié)束移動滑塊的布爾值。我們可以使用它來高亮顯示編輯中的值,如下例所示。
示例6-37:響應(yīng)滑塊狀態(tài)
struct ContentView: View {@State private var currentValue: Float = 5@State private var textAcitve: Bool = falsevar body: some View {VStack {Text("Current Value: \(currentValue.formatted(.number.precision(.fractionLength(0))))").padding().background(textAcitve ? Color.yellow : Color.clear)Slider(value: $currentValue, in: 0...10, step: 1.0, onEditingChanged: { self.textAcitve = $0 })Spacer()}.padding()}
}
示例6-37中的視圖包含一個(gè)名為??textActive?
?的新??@State?
?屬性。賦值給閉包的??onEdittingChanged?
?參數(shù)在用戶開始移動滑塊時(shí)對該屬性賦值??true?
?,釋放結(jié)點(diǎn)時(shí)賦值??false?
?。??Text?
?視圖的??background()?
?修飾符讀取該值根據(jù)當(dāng)前狀態(tài)設(shè)置不同的背景色。因此,在用戶移動滑塊時(shí)顯示當(dāng)前值的文本為黃色背景,否則沒有背景色。
進(jìn)度視圖
SwiftUi內(nèi)置有??ProgressView?
?視圖來用于創(chuàng)建進(jìn)度條。該視圖設(shè)計(jì)用于顯示任務(wù)的進(jìn)度。
- ProgressView(String, value: Binding, total: Double):此初始化方法創(chuàng)建一個(gè)進(jìn)度條。第一個(gè)參數(shù)指定標(biāo)簽,?
?value?
?參數(shù)表示當(dāng)前進(jìn)度,??total?
?參數(shù)指定表示任務(wù)完成度的值。(默認(rèn)值為0.0到1.0)。
視圖的實(shí)現(xiàn)非常直觀。我們只需要一個(gè)表示當(dāng)前進(jìn)度的屬性值。
示例6-38:顯示進(jìn)度
struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView(value: currentValue, total: 10)Spacer()}.padding()}
}
這一??ProgressView?
?視圖值由0.0到10.0,初始值為5(通過??currentValue?
?賦了初始值),因此進(jìn)度位于中心。
圖6-24:進(jìn)度條
??ProgressView?
?視圖設(shè)計(jì)用于顯示任務(wù)即時(shí)的進(jìn)度,比如從服務(wù)端下載的當(dāng)前數(shù)據(jù)量,或是還差多少完成任務(wù)。稍后我們會學(xué)習(xí)如何執(zhí)行其中一些任務(wù),但現(xiàn)在我們通過??Slider?
?視圖來做測試,如下所示。
示例6-39:模擬進(jìn)度
struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView(value: currentValue, total: 10)Slider(value: $currentValue, in: 0...10)Spacer()}.padding()}
}
本例中,我們對??Slider?
?和??ProgressView?
?設(shè)置了相同的值。范圍為0到10,因此每當(dāng)我們移動滑塊時(shí),進(jìn)度條就顯示相同值。
圖6-25:使用中的進(jìn)度條
??ProgressView?
?結(jié)構(gòu)體內(nèi)置了如下修飾符用于定義進(jìn)度條的樣式。
- progressViewStyle(ProgressViewStyle):這一修飾符指定?
?ProgressView?
?視圖的顏色 。參數(shù)是一個(gè)遵循??ProgressViewStyle?
?協(xié)議的結(jié)構(gòu)體??蚣芏x了??automatic?
?、??circular?
?和??linear?
?屬性來創(chuàng)建標(biāo)準(zhǔn)視圖。
默認(rèn)樣式為??automatic?
?,表示視圖顯示為一個(gè)線性進(jìn)度條,但我們可以指定??circular?
?值來創(chuàng)建活動指示。這是一個(gè)表示任務(wù)在處理中的轉(zhuǎn)盤,但不同于進(jìn)度條,這類指示符沒有隱性界限,所示無需指定任何值,如下所示。
示例6-40:顯示活動指示器
struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView().progressViewStyle(.circular)Spacer()}.padding()}
}
圖6-26:活動指示器
其它相關(guān)內(nèi)容請見??虛擬現(xiàn)實(shí)(VR)/增強(qiáng)現(xiàn)實(shí)(AR)&visionOS開發(fā)學(xué)習(xí)筆記??