實戰教程·元宇宙來了,準備好你的電子名片了嗎?(三)

語言: CN / TW / HK

theme: smartblue

前提回顧

在上兩個章節中,我們完成了個人主頁以及新增身份卡頁面的設計,其中學習如何資料模型、列表建立卡片展示檢視,以及開啟頁面和關閉頁面的互動動作,在本章節中,我們來學習搭建新增身份卡頁面的相關內容。

介面分析:頁面元素及其優先順序

新增身份卡頁面,需要根據個人主頁身份卡的內容來構建,身份卡對應展示的資訊,就是我們需要在新增時建立的資訊,如下圖所示:

對於資訊的優先順序,主要資訊為平臺稱號,其次資訊是平臺圖示和平臺名稱,再次隱藏資訊是連結地址。

確定頁面元素的優先順序需要遵循使用者慣性邏輯以及應用想給使用者呈現的關鍵點,在身份卡中對於使用者而言最核心的資訊是在平臺所取得的稱號,而平臺稱號也是在個人主頁身份卡中使用者視線首要關注的內容。

其次的平臺資訊部分,由平臺圖示和平臺名稱組成,這是由於這兩塊資訊具有相關性,平臺名稱對應著平臺圖示,因此在產品設計上可以耦合在一起。

最後是連結地址部分,後續我們希望關聯對應平臺地址後,能點選身份卡片在應用內開啟瀏覽器並訪問連結地址,而連結地址在整個身份卡片中是不展示其內容的,因此資訊的優先順序可以放置至最後。

變數宣告:身份卡必要引數準備

分析完介面元素後,我們在建立頁面之前先確定好需要使用到的變數,如下程式碼所示:

@State var platformIcon: String = "icon_juejin" @State var title: String = "移動端簽約作者" @State var platformName: String = "稀土掘金技術社群" @State var indexURL: String = "https://juejin.cn/user/3897092103223517"

上述程式碼中,我們都使用@State進行變數的宣告,@State可以儲存宣告的變數及其變數的值。並且為了呈現效果,我們給宣告的引數都賦予了初始值。

介面設計:平臺稱號輸入框

宣告好需要的變數後,我們來搭建平臺稱號輸入框內容,我們可以和搭建closeBtn關閉按鈕檢視一樣,單獨搭建平臺輸入框檢視,再將該檢視內容賦予NewView主要的檢視中,如下程式碼所示:

// 頭銜名稱輸入框 func titleInputView() -> some View { TextField("請輸入頭銜", text: $title) .padding() .background(Color(.systemGray6)) .cornerRadius(8) .padding(.horizontal) }

上述程式碼中,我們建立了一個平臺稱號輸入框檢視titleInputView,主體內容使用TextField輸入框控制元件,輸入框提示文字為“請輸入頭銜”,輸入內容繫結宣告的變數title。

在樣式方面,為了突出輸入框檢視內容,使用padding修飾符“撐開”輸入框外層區域,將外層區域填充背景色為systemGray6,並設定圓角度數為8,最後設定水平位置兩邊留白,便實現了上圖效果。

介面設計:自定義平臺選擇器

接下來我們來設計“選擇平臺”的操作邏輯。可以簡單設想下,使用者在“新增身份卡”頁面輸入完平臺稱號後,下一步是選擇該稱號所在的社群或者平臺。

最直觀的展現方式是將平臺都排列出來讓使用者進行選擇,而由於展示空間有限,我們可以只展示平臺的圖示。當用戶看到平臺圖示時,通過點選選擇以確定平臺,而且平臺選擇單張身份卡只能選擇一個平臺。

有了基礎的想法後,我們來實現這個互動邏輯。

首先需要建立一個平臺展示的資料集合,我們宣告一個數據用於存放資料,如下程式碼所示:

private let platforms = [ ("稀土掘金技術社群", "icon_juejin"), ("CSDN部落格", "icon_csdn"), ("阿里雲社群", "icon_aliyun"), ("華為雲社群", "icon_huaweiyun"), ]

上述程式碼中,我們聲明瞭一個常量陣列platforms,在platforms陣列內有兩個內容,前一個引數是平臺名稱,後一個引數是平臺圖示。

宣告好資料後,我們來建立平臺選擇樣式部分,這次需要用到的SwiftUI控制元件是LazyVGrid垂直網格佈局容器,LazyVGrid垂直網格佈局容器類似VStack垂直佈局容器,不同的是VStack垂直佈局容器只能將內部的元素垂直排布,而LazyVGrid垂直網格檢視容器可以保持垂直佈局的情況下,將內部的元素分為幾列,如下圖所示:

LazyVGrid垂直網格佈局容器使用需要提前宣告網格的列數,如下程式碼所示:

private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]

上述程式碼中,我們聲明瞭佈局容器的GridItem列項為4列自適應調整的列項,將引數賦予變數值gridItemLayout。

緊接著我們來使用LazyVGrid垂直網格佈局容器,LazyVGrid垂直網格佈局容器的使用方法和List列表的使用方法類似,通過與ForEach迴圈遍歷配合使用,我們依舊使用單獨構建檢視的方法建立它,如下程式碼所示:

// 平臺選擇器 func platformPicker() -> some View { LazyVGrid(columns: gridItemLayout, spacing: 10) { ForEach(0 ..< platforms.count, id: .self) { item in Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) } } }

上述程式碼中,我們建立了“選擇平臺”檢視platformPicker,在platformPicker檢視中使用LazyVGrid垂直網格佈局容器搭建網格檢視,LazyVGrid的columns列項為上面宣告的gridItemLayout,網格之間元素的spacing間距為10。

和List列表的方法一樣,我們使用ForEach迴圈遍歷platforms陣列的資料,並使用了Image圖片控制元件來展示platforms陣列中的資料。由於platforms陣列使用兩個資料,因此我們使用下標法指向陣列的第二個資料(計算機資料從0開始計數)。

在這裡還需要考慮一個問題,當我們平臺圖示太多時,可能會佔據整個App的頁面,我們可以在LazyVGrid垂直網格佈局容器最外層增加一個ScrollView滾動檢視容器,並設定滾動檢視的高度,如此LazyVGrid垂直網格佈局容器不管有多少元素,都只會在ScrollView滾動檢視容器中展示,如下程式碼所示:

ScrollView { LazyVGrid(columns: gridItemLayout, spacing: 10) { ForEach(0 ..< platforms.count, id: .self) { item in Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) } } } .padding() .background(Color(.systemGray6)) .cornerRadius(8) .padding(.horizontal) .frame(maxHeight: 180)

很好,完成了“平臺選擇器”的樣式之後,我們來實現互動邏輯部分,首先我們要看到使用者點選選擇的平臺是哪一個,並將其凸顯出來。

由於ForEach是遍歷資料給到了item,因此當用戶點選了指定的item時,該item對應的樣式與其他未選中的樣式分隔開。為了實現這個效果,我們首先要宣告一個變數,知道選中的是哪一個item,如下程式碼所示:

@State var selectedItem = 0

當選中時,即item的值等於selectedItem時,我們設定圖片加一層邊框,如果不是,則保持原樣,如下程式碼所示:

if item == selectedItem { Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) .overlay( Circle() .stroke(Color.green, lineWidth: 4) ) } else { Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) .onTapGesture { selectedItem = item } }

上述程式碼中,我們通過判斷當前的item是否等於selectedItem來構建不同的圖片樣式,如果一致,則Image圖片使用overlay修飾符覆蓋一層綠色的圓形邊框。如果不一致,則保持原來的樣式,在原有的樣式上增加onTapGesture點選事件,當點選的時候,讓selectedItem選中的item等於點選的item。

可以在模擬器上試試效果,如下圖所示:

另外,當點選平臺圖示時,我們需要給宣告的變數進行賦值,如下程式碼所示:

platformIcon = platforms[item].1 platformName = platforms[item].0

如此,便完成了“自定義平臺選擇器”的所有內容。

介面設計:連結地址多行文字框

接下來我們來完成連結地址的互動設計,TextEditor多行文字框控制元件和TextField輸入框控制元件的使用方法類似,不同的是至今TextEditor多行文字框控制元件都沒有提供placeholder提示文字的設定方法,只能由開發者自行實現。

不過沒關係,實現多行文字框的方法及其提示文字的方法也很簡單,如下程式碼所示:

``` // 連結地址 func indexURLView() -> some View { ZStack(alignment: .topLeading) { TextEditor(text: $indexURL) .font(.system(size: 17)) .padding(15)

    if indexURL.isEmpty {
        Text("請輸入主頁連結")
            .foregroundColor(Color(UIColor.placeholderText))
            .padding(20)
    }
}
.background(Color(.systemGray6))
.cornerRadius(8)
.padding()
.frame(maxHeight: 240)

} ```

上述程式碼中,我們建立了一個多行文字框檢視indexURLView作為連結地址的輸入框,在indexURLView檢視中使用ZStack堆疊檢視建立層級關係,當TextEditor輸入框的繫結的內容indexURL為空時,則展示一個Text文字作為提示文字。

如此就實現了TextEditor多行文字框及其提示文字的互動。

互動設計:新增身份卡按鈕及其方法

完成新增身份卡的頁面元素後,我們來實現將輸入的內容新增到“個人主頁”的方法。

首先我們先建立基本的按鈕,如下程式碼所示:

// 新增按鈕 func addBtn() -> some View { Button(action: { }) { Text("新增") .font(.system(size: 17)) .foregroundColor(.white) .bold() .padding() .frame(maxWidth: .infinity) .background(Color.green) .cornerRadius(8) .padding(.horizontal) } }

回到NewView的Body部分,所有元素我們均以搭建完成,所有檢視的排布我們可以使用VStack垂直佈局容器進行排布,如下程式碼所示:

``` VStack(spacing: 15) { titleInputView()

platformPicker()

indexURLView()

addBtn()

Spacer()

} ```

樣式完成之後,我們來實現新增身份卡到個人主頁的互動。

我們來到Model.swift資料模型檔案,原來我們聲明瞭models陣列變數,我們需要將其剪下到ContentView檔案中來,作為ContentView中的一部份,用於後面的資料雙向繫結使用,如下圖所示:

然後回到NewView檔案中,宣告用於雙向繫結的資料模型,如下程式碼所示:

@Binding var models: [Model]

由於使用了@Binding進行雙向繫結引數,因此NewView中不能存在private宣告的變數,因此我們需要刪除原來platforms陣列和gridItemLayout網格佈局的private,並且給NewView賦予預設值,如下程式碼所示:

NewView(models: .constant([]))

還需要回到ContentView檔案,對使用NewView檢視中宣告的雙向繫結的models進行繫結,如下圖所示:

最後我們還需要回到NewView檢視中,實現新增身份卡的方法,如下程式碼所示:

let newItem = Model(platformIcon: platformIcon, title: title, platformName: platformName, indexURL: indexURL) models.append(newItem)

上述程式碼中,我們在點選addBtn新增按鈕時,實現新增身份卡的方法,首先先宣告一個常量newItem存放符合Model資料模型的資料,並將資料模型的對應的值填充為我們在NewView宣告的變數(由於採用一樣的命名,因此就有了上面的效果),然後呼叫append的方法將符合資料模型的資料新增到models陣列中。

此時我們就可以刪除NewView中宣告的變數的預設值,讓使用者自定定義填充,如下程式碼所示:

@State var title: String = "" @State var indexURL: String = ""

同時我們也可以刪除在ContentView中models陣列的預設值,讓我們自己操作建立資料,如下程式碼所示:

@State var models:[Model] = []

整體預覽

接下來,讓我們在模擬器中操作電子名片App的全路徑,如下圖所示:

iShot_2022-11-13_17.19.38.gif

本章小結

在本章中,我們學習瞭如何搭建“新增身份卡”頁面,包含輸入框基礎控制元件的使用,多行文字框基礎控制元件的使用。

本章的核心內容是自定義選擇器的建立,我們使用ScrollView滾動檢視容器、LazyVGrid垂直網格容器搭建了選擇器,並實現了單選的功能。最後我們通過雙向繫結檢視陣列資料的方式,實現了新增身份卡到個人主頁的方法。

在本章的例子中,其實可以運用到其他App案例中,最常見的示例:todo待辦事項和note筆記。

下面的章節中,我們來繼續學習點選身份卡片在App開啟瀏覽器並訪問連結地址的功能及其他相關操作,請保持期待吧~

版權宣告

本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!

「其他文章」