實戰程式設計·刻在男人DNA裡的浪漫,空氣投籃(一)
theme: smartblue
專案背景
和往常一樣的下午,午後的陽光灑在身上,感覺有些舒服。突然腦海裡閃過一個念頭,小步快跑,起身,雙手舉起,目視前方,揮手投籃,唰.........最近一款APP幾乎引起了所有男孩子的興趣,這就是空氣投籃。
想起年少時和一群朋友走在路上,男孩子們都或多或少做過這種“傻傻的”動作,那是青春的味道。
而竟然有家公司將它做了出來,一時間馬上下載、安裝.......額.......這.......需要AppleWatch才能用。好吧,竟然沒有辦法體驗空氣投籃,不如就用用自己的專長,畫畫iOS端的頁面吧。
專案搭建
首先開啟Xcode,建立一個新的SwiftUI專案,命名為AirBall,如下圖所示:
空氣投籃分為iOS端和Watch,本章我們先來完成iOS的相關頁面。iOS端頁面操作及其流程如下圖所示:
實戰程式設計
準備遊戲檢視
首先是準備遊戲檢視,簡單分析可知,它由文字Text和圖片Image組成,背景顏色填充為黑色。Image圖片部分,需要匯入一張SVG適量圖片,使得其很好地與背景融合。如下圖所示:
匯入完成後,我們來構建頁面部分。在ContentView檔案中,我們鍵入以下程式碼:
``` // 準備遊戲 func prepareView() -> some View { VStack(alignment: .center, spacing: 80) { Spacer() Text("請確定你已啟用Apple Watch上的空氣投籃App") .font(.system(size: 17)) .foregroundColor(.white) .lineLimit(2) .lineSpacing(15) .multilineTextAlignment(.center)
Image("watch_application")
.resizable()
.aspectRatio(contentMode: .fit)
Spacer()
Spacer()
}.frame(maxWidth: Constants.screenWidth / 2)
} ```
上述程式碼中,我們建立了一個新的View檢視prepareView準備開始遊戲檢視。
在prepareView檢視中,文字Text和Image圖片使用VStack垂直佈局容器包裹,並設定其對齊方式為居中對齊,容器內容元素間距為80。
Text文字部分的處理為設定font字型為17號字,設定foregroundColor填充色為白色,由於文字過長可能導致頁面無法展示的原因,這裡設定lineLimit文字顯示行數為2行,並設定換行時multilineTextAlignment文字對齊方式為居中對齊。
Image圖片部分,設定resizable圖片縮放,並設定aspectRatio保持原本的寬高比避免變形。
最後使用frame設定VStack垂直佈局容器的寬度,為螢幕寬度的一半。為了增強使用者體驗,在VStack垂直佈局容器中使用Spacer佔位符,下方設定2個,上方設定一個,這個視覺元素就會展示在螢幕上部分2/3的位置,又是一個小技巧。
完成後,我們在Body中展示,如下程式碼所示:
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
prepareView()
}
上述程式碼中,我們使用ZStack疊加檢視,將prepareView準備遊戲檢視和Color顏色疊加,顏色部分使用edgesIgnoringSafeArea忽略全部安全區域,便可讓黑色背景鋪滿整個螢幕。
遊戲列表檢視
開啟App,進入準備遊戲檢視,此時需要與Watch端聯動,在Watch端確認後,iOS端將進入至遊戲列表頁面。
遊戲列表頁面的互動邏輯是,點選遊戲卡片則進入到遊戲中,在遊戲列表頁左右滑動可切換遊戲。
我們先來完成單張遊戲卡片的設計。分析得知,單張遊戲卡片的內容包括3塊內容:遊戲專案、遊戲說明、遊戲封面。
我們建立一個新的檢視,程式碼如下所示:
``` // MARK: 遊戲項
struct gameRowView: View {
var gameName: String
var gameHelpText: String
var gameImage: String
var body: some View {
VStack(alignment: .center, spacing: 60) {
Text(gameName)
.font(.system(size: 48))
.bold()
.foregroundColor(.white)
VStack(alignment: .center, spacing: 10) {
Text(gameHelpText)
.font(.system(size: 17))
.foregroundColor(.white)
Image(gameImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight:UIScreen.main.bounds.size.width - 20)
}
}
}
} ```
上述程式碼中,我們建立了一個新的結構體gameRowView遊戲項檢視。
之所以建立一個新的結構體,而沒有和上面prepareView準備遊戲檢視一樣直接定義View檢視,是因為我們需要將gameRowView遊戲項檢視作為“母版”,然後按照單個gameRowView遊戲項檢視構建多個一樣樣式的遊戲卡片。
在gameRowView遊戲項檢視中,我們聲明瞭3個String型別的變數:gameName遊戲名稱、gameHelpText遊戲說明、gameImage遊戲封面。
然後在其Body中建立樣式,由於遊戲名稱的Text和其餘兩塊在頁面上還是有些距離,這裡使用了2個VStack垂直佈局容器,將遊戲說明和遊戲封面放在一個容器中,它們直接的間距為10,而再用一個VStack垂直佈局容器再把遊戲標題包裹在一起,間距為60。
這裡額外再補充一個知識點。
就是遊戲封面使用frame設定其大小的問題,由於我們匯入的遊戲封面圖片可能存在大小不一致的問題,因此如果需要讓這個遊戲卡片看起來元素位置保持一致,由於使用了VStack垂直佈局容器,因此,可以設定圖片maxHeight高度為螢幕width寬度,再減去20留點邊距。
這樣做,無論圖片尺寸是多少,每個遊戲卡片展示的遊戲名稱、遊戲說明、遊戲封面的位置就保持一致了。
我們匯入兩張SVG格式的遊戲圖片作為素材使用,如下圖所示:
遊戲卡片是左右滑動切換的互動,這時我們就可以在ContentView檢視中再建立一個View檢視構建它,如下程式碼所示:
// 遊戲列表
func gameListView() -> some View {
TabView {
gameRowView(gameName: "投籃", gameHelpText: "手舉球開始遊戲", gameImage: "basketball")
gameRowView(gameName: "打棒球", gameHelpText: "雙手揮動開始遊戲", gameImage: "baseball")
}
.tabViewStyle(PageTabViewStyle())
}
上述程式碼中,我們建立了一個遊戲列表檢視gameListView。
然後使用TabView滾動檢視容器包裹了2個gameRowView遊戲項檢視,遊戲項檢視中我們給宣告的變數賦值以顯示內容。最後設定TabView滾動檢視的樣式,為PageTabViewStyle分頁滾動型別,如此便實現了橫向切換遊戲卡片的互動。
本章程式碼
為方便學習,本章完整程式碼如下所示:
``` import SwiftUI
struct ContentView: View { var body: some View { ZStack { Color(.black).edgesIgnoringSafeArea(.all)
gameListView()
}
}
// 準備遊戲
func prepareView() -> some View {
VStack(alignment: .center, spacing: 80) {
Spacer()
Text("請確定你已啟用Apple Watch上的空氣投籃App")
.font(.system(size: 17))
.foregroundColor(.white)
.lineLimit(2)
.lineSpacing(15)
.multilineTextAlignment(.center)
Image("watch_application")
.resizable()
.aspectRatio(contentMode: .fit)
Spacer()
Spacer()
}.frame(maxWidth: UIScreen.main.bounds.size.width / 2)
}
// 遊戲列表
func gameListView() -> some View {
TabView {
gameRowView(gameName: "投籃", gameHelpText: "手舉球開始遊戲", gameImage: "basketball")
gameRowView(gameName: "打棒球", gameHelpText: "雙手揮動開始遊戲", gameImage: "baseball")
}
.tabViewStyle(PageTabViewStyle())
}
}
// MARK: 遊戲項
struct gameRowView: View { var gameName: String var gameHelpText: String var gameImage: String
var body: some View {
VStack(alignment: .center, spacing: 60) {
Text(gameName)
.font(.system(size: 48))
.bold()
.foregroundColor(.white)
VStack(alignment: .center, spacing: 10) {
Text(gameHelpText)
.font(.system(size: 17))
.foregroundColor(.white)
Image(gameImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: UIScreen.main.bounds.size.width - 20)
}
}
}
}
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } ```
本章小結
首先恭喜你,完成了本章的介紹的所有內容!
空氣投籃iOS端的頁面目前我們只完成了前2張,接下來,我們將繼續完成其餘的頁面及其互動,以及後面也會切換到Watch端,完成空氣投籃Watch端的相關頁面設計。
總的來說,空氣投籃App的頁面及其互動並不複雜。
這個專案很小,卻實實在在戳中了很多使用者的內心。彷彿某些個人“很傻”的小習慣被大眾所認知、所接受,這種滿足感剛好刺激到了某個痛點,很小,但很痛。
這可能就是一款好的產品的象徵,也應該是每個提供產品服務的企業所追求的。
望共勉之~
版權宣告
本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(一)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(八)
- 實戰教程·什麼年代了還在敲傳統木魚?(二)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(七)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(六)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(五)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(四)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(三)
- 實戰教程·元宇宙來了,準備好你的電子名片了嗎?(二)
- 實戰教程·什麼年代了還在敲傳統木魚?(一)
- 技術下午茶:產品經理是如何工作的?如何才算一份好的需求文件?如何設計一個簡單的列表,它應該具備哪些基本功能?
- 釋出&選擇釋出,使用SwiftUI搭建一個新建釋出彈窗(上)
- 釋出&選擇釋出,使用SwiftUI搭建一個新建釋出彈窗(下)
- 使用SwiftUI搭建一個風箏搖擺動畫,實現放風箏的夢想~
- SwiftUI100天:使用SwiftUI搭建一個計時器App
- 實戰程式設計·使用SwiftUI從0到1完成一款iOS筆記App(三)
- 初識MVVM·關於啟動頁、引導頁、登入頁的設計細節和互動邏輯
- 誰說程式設計師不懂浪漫,教你使用SwiftUI搭建一個電子相簿送給她吧~
- 實戰程式設計·刻在男人DNA裡的浪漫,空氣投籃(二)
- 實戰程式設計·使用SwiftUI從0到1完成一款iOS筆記App(四)