實戰教程·元宇宙來了,準備好你的電子名片了嗎?(二)
theme: smartblue
前提回顧
在上一章中,我們建立了CardView構件,使用了構件程式設計方式搭建檢視。使用構件的好處是當我們要整體修改構件內容時,就可以只修改構件的結構體,而無需每個卡片檢視都修改。
示例,在上一章中我們設定了平臺圖示圖片,但由於平臺圖示樣式的不統一性,看起來有些不協調。這時候,我們可以給CardView構件中的Image控制元件設定為圓形,讓其更加美觀些,如下圖所示:
對於搭建好的構件,只需要修改CardView構件本身,就可以在引用此構件的所有地方統一修改其樣式。
是不是很方便?接下來讓我們繼續完成下面的內容。
結構化程式設計:搭建資料模型
使用構件建立身份卡片檢視後,我們發現如果每次要新增一個卡片,就需要在卡片檢視中需要複製CardView構件並賦值。當我們需要建立很多身份卡片時,就會需要很多一樣的程式碼,這不夠優雅。
有沒有辦法像搭建CardView構件一樣,只搭建一個結構然後填充資料,讓結構自動“遍歷”出內容?
SwiftUI宣告式語言中,可以使用List列表元件迴圈遍歷內容,在此之前我們需要定義好資料模型。我們建立一個新的Swift檔案,命名為Model,如下圖所示:
Model檔案作為我們搭建資料模型的檔案,定義資料需要宣告的變數。首先我們引用SwiftUI,如下程式碼所示:
import SwiftUI
接下來搭建資料模型,如下程式碼所示:
struct Model: Identifiable {
var id = UUID()
var platformIcon: String
var title: String
var platformName: String
var indexURL: String
}
資料模型可以使用Class類或者Struct結構體宣告,這裡我們使用Struct結構體聲明瞭一個數據模型Model,遵循Identifiable協議。“Identifiable可識別”協議可以通過id區分不同的資料,當我們建立的資料中有兩條一模一樣的資料時,由於“Identifiable可識別”協議,系統將賦予不同的id,實現呈現兩條資料內容的效果。
使用Identifiable協議除了宣告需要的引數變數外,還需要在資料模型中宣告一個id,並複製為UUID。該資料模型中的需要使用的變數引數,我們可以直接使用之前在CardView身份卡片構件宣告的引數。
宣告好引數後,我們為展示資料,可以建立一個數據陣列作為示例資料,如下程式碼所示:
``` // MARK: 示例資料
var models = [ Model(platformIcon: "icon_juejin", title: "移動端簽約作者", platformName: "稀土掘金技術社群", indexURL: "http://juejin.cn/user/3897092103223517"), Model(platformIcon: "icon_csdn", title: "iOS創作者", platformName: "CSDN部落格", indexURL: ""), Model(platformIcon: "icon_aliyun", title: "專家博主", platformName: "阿里雲社群", indexURL: ""), Model(platformIcon: "icon_huaweiyun", title: "專家博主", platformName: "華為雲社群", indexURL: ""), ] ```
如此便完成了資料模型的搭建。
卡片檢視:List列表和ForEach迴圈
我們回到ContentView檢視中,刪除原有的身份卡片檢視的程式碼。卡片檢視我們可以看作一個列表,每張身份卡片就是一行行呈現的資料,列表的資料來源則來源於上述建立好的陣列models,如下圖所示:
List {
ForEach(models) { item in
CardView(platformIcon: item.platformIcon, title: item.title, platformName: item.platformName, indexURL: item.indexURL)
}
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
}
上述程式碼中,我們使用List列表和ForEach迴圈結構,遍歷models陣列中定義好的資料內容,並在呼叫CardView身份卡片構件的時候賦值為迴圈後item的一條條資料。
由於演示的iPhonex模擬器,因此為了呈現更好的列表樣式效果,使用listRowBackground列表項背景修飾符,將列表背景顏色修飾為透明。並使用listRowSeparator列表分割線修飾符,隱藏List自帶的分割線。完成這些操作後後,就可以完成展示身份卡片構件的樣式內容。
在模擬器中預覽的效果中,身份卡片左右邊距太寬了,我們可以直接修改CardView構件的程式碼,去掉最後的padding邊距,如下圖所示:
導航選單:標題和新建卡片入口
卡片檢視完善之後,我們來搭建頂部導航選單。SwiftUI提供了NavigationView導航檢視控制元件方便我們快速搭建應用的頂部導航選單。從檢視層級來看,頂部導航選單是“包裹”整個頁面檢視的,因此NavigationView導航檢視控制元件需要在ContentView的body檢視最外層,如下程式碼所示:
NavigationStack {
//檢視內容
.navigationBarTitle("文如秋雨",displayMode: .inline)
}
在iOS16版本,使用NavigationStack導航檢視控制元件搭建頂部導航選單,iOS16版本以下的機型使用NavigationView導航。
搭建好頂部導航欄後,我們建立一個新的按鈕,作為建立身份卡片的入口。可以使用navigationBarItems導航欄按鈕修飾符建立導航選單上的按鈕入口,不過在此之前,我們需要搭建好按鈕的檢視,再將按鈕賦予navigationBarItems導航欄按鈕修飾符。如下程式碼所示:
``` func addBtn() -> some View { Button(action: {
}) {
Image(systemName: "plus.circle.fill")
.font(.system(size: 17))
.foregroundColor(.blue)
}
}
```
上述程式碼中,我們完成了一個按鈕檢視addBtn。一般在程式設計過程中,若檢視中除樣式程式碼外還有互動操作,通常會將其抽離出來作為一個單獨的檢視進行構建,然後再在修飾符或者其他檢視中使用,這是SwiftUI開發中經常會遇到的事情。
完成按鈕檢視的構建後,我們將按鈕檢視加到頂部導航選單中,如下程式碼所示:
.navigationBarItems(trailing: addBtn())
模態彈窗:開啟一個新頁面
個人主頁部分基本已經完成了,下面我們來完成點選頂部導航選單的“新增”按鈕,開啟“新建身份卡”頁面。
首先我們先建立一個新的SwiftUI檔案,命名為NewView,如下圖所示:
回到ContentView檢視中,使用Sheet模態彈窗控制元件,建立開啟彈窗的樣式,如下程式碼所示:
.sheet(isPresented:Is Presented) {
Content
}
上述程式碼中,我們使用sheet修飾符控制元件搭建開啟模態彈窗效果,但需要使用sheet修飾符控制元件,需要提前宣告好觸發開啟動作的變數,如下程式碼所示:
@State var showNewView:Bool = false
並將宣告好的觸發變數繫結到sheet修飾符控制元件中,以及設定Content跳轉的頁面目標為NewView。如下程式碼所示:
.sheet(isPresented: $showNewView) {
NewView()
}
最後在點選addBtn按鈕檢視時,切換showNewView開啟檢視的變數狀態,便可實現點選“新增按鈕”開啟模態彈窗,如下程式碼所示:
self.showNewView.toggle()
關閉彈窗的方法也很類似,我們來到NewView檢視,給NewView檢視的內容新增頂部導航選單,並也建立一個關閉彈窗的按鈕,如下程式碼所示:
``` struct NewView: View { var body: some View { NavigationStack { Text("Hello, World!") .navigationBarTitle("新增身份卡", displayMode: .inline) .navigationBarItems(trailing: closeBtn()) } }
func closeBtn() -> some View {
Button(action: {
}) {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 17))
.foregroundColor(.gray)
}
}
} ```
上述程式碼中,我們使用的方法和個人主頁的內容基本一致,使用NavigationStack導航選單控制元件建立導航選單,並使用navigationBarTitle頂部導航標題控制元件建立標題。單獨建立關閉按鈕檢視closeBtn,並將它賦予導航選單中的navigationBarItems導航選單欄目修飾符,以建立導航選單上的按鈕。
關閉彈窗:雙向繫結或全域性變數
實現開啟模態彈窗後,我們來實現關閉模態彈窗,下面我們來介紹兩種關閉模態彈窗的方法:雙向繫結、全域性變數。
由於我們在ContentView個人主頁聲明瞭一個變數showNewView來開啟模態彈窗,當點選addBtn按鈕時更新其狀態。因此我們也可以在NewView頁面中也宣告一個雙向繫結的變數showNewView,並在點選closeBtn時更新其狀態,實現關閉彈窗的互動。
首先先宣告一個雙向繫結的變數showNewView如下圖所示:
@Binding var showNewView:Bool
然後在點選closeBtn關閉按鈕時更新其狀態,如下程式碼所示:
self.showNewView.toggle()
由於使用@Binding宣告變數,因此在NewView檢視中宣告的變數缺少賦值,將可能導致無法預覽,因此我們在預覽時需要給NewView檢視賦予預設值,如下程式碼所示:
NewView(showNewView: .constant(false))
建立雙向繫結的檢視,在所有頁面也都需要進行@Binding宣告變數的繫結,因此我們回到ContentView檢視中,繫結showNewView變數,如下程式碼所示:
NewView(showNewView: $showNewView)
完成後,可以在模擬器中操作開啟模態彈窗和關閉模態彈窗的互動。
另一種關閉模態彈窗的方法是宣告一個全域性變數,實現關閉彈窗的效果,如下程式碼所示:
``` //宣告環境變數 @Environment(.presentationMode) var presentationMode
//呼叫 self.presentationMode.wrappedValue.dismiss() ```
上述程式碼中,我們聲明瞭一個全域性變數presentationMode,在點選closeBtn關閉按鈕的時候呼叫presentationMode全域性變數的wrappedValue.dismiss方法實現關閉彈窗效果。
兩種方式在實際開發過程中均有使用,除模態彈窗外,在頁面之間使用入棧出棧的方式進行切換頁面也經常會用到。
在模態彈窗互動邏輯中更經常使用全域性變數關閉彈窗的方式,無需進行雙向繫結已經給檢視新增預設值,也就無需示例在其他頁面缺少繫結引數的麻煩。
本章小結
在本章中,我們主要實現了使用資料模型和List列表來構建身份卡片檢視的內容,在減少程式碼量的同時,其實也是為了之後對身份卡片進行新增、編輯、刪除做前期準備。
在SwiftUI中,複雜的具有相似結構的介面設計,通常會使用List列表和ForEach來實現,常見的類似Todo待辦事項App中的卡片列表、資訊流App的資訊列表、短視訊平臺的視訊封面卡片檢視等等。
另外我們還學習了使用NavigationStack導航選單控制元件(iOS16版本及以上機型使用,低於此版本機型使用NavigationView,Apple經常會在新控制元件完善後棄用舊控制元件,這點有點煩)及其標題、導航按鈕修飾符的使用,並進一步瞭解了使用sheet模態彈窗修飾符開啟彈窗。關閉彈窗部分,我們介紹了兩種方式實現關閉彈窗,並簡單介紹了其使用特點。
在下面的章節中,我們將繼續完成“新增身份卡”頁面的相關操作,請保持期待吧~
版權宣告
本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(一)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(八)
- 實戰教程·什麼年代了還在敲傳統木魚?(二)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(七)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(六)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(五)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(四)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(三)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(二)
- 實戰教程·什麼年代了還在敲傳統木魚?(一)
- 技術下午茶:產品經理是如何工作的?如何才算一份好的需求文件?如何設計一個簡單的列表,它應該具備哪些基本功能?
- 釋出&選擇釋出,使用SwiftUI搭建一個新建釋出彈窗(上)
- 釋出&選擇釋出,使用SwiftUI搭建一個新建釋出彈窗(下)
- 使用SwiftUI搭建一個風箏搖擺動畫,實現放風箏的夢想~
- SwiftUI100天:使用SwiftUI搭建一個計時器App
- 實戰程式設計·使用SwiftUI從0到1完成一款iOS筆記App(三)
- 初識MVVM·關於啟動頁、引導頁、登入頁的設計細節和互動邏輯
- 誰說程式設計師不懂浪漫,教你使用SwiftUI搭建一個電子相簿送給她吧~
- 實戰程式設計·刻在男人DNA裡的浪漫,空氣投籃(二)
- 實戰程式設計·使用SwiftUI從0到1完成一款iOS筆記App(四)