前提回顾
在上一章节中,咱们完结了“预备游戏”页面和“游戏列表”页面,并完结了游戏列表的简单交互,在本章中,咱们将持续完结其他的相关内容。
实战编程
页面切换
在整个空气投篮项目中,“预备游戏”页面和“游戏列表”页面的交互逻辑是,翻开App展现“预备游戏”页面,同时唤起Watch端的授权,授权通往后,进入到“游戏列表”页面。
当时Watch端先行忽略,咱们先完结切换切换的逻辑。首要声明一个变量存储切换动作,如下代码所示:
@State var isAffirmInWatch: Bool = false
上述代码中,咱们声明晰一个Bool类型的变量isAffirmInWatch
,初始状况位false。
当isAffirmInWatch是否授权状况为true时,咱们进入到gameListView游戏列表页面,若没有授权,则停留在prepareView预备游戏页面。如下代码所示:
if isAffirmInWatch {
gameListView()
} else {
prepareView()
.onTapGesture {
self.isAffirmInWatch = true
}
}
上述代码中,为了演示方便,咱们给prepareView预备游戏视图加了一个onTapGesture点击事情,当点击prepareView预备游戏视图时,切换isAffirmInWatch是否授权状况为true,如此在点击时便可进入到gameListView游戏列表视图。
游戏回合视图
接下来,当用户点击游戏列表的游戏项时,需求进入到游戏概况页。
而对于“投篮项目”来说,一般有3~5个回合,在正式游戏开端之前,会展现一个类似“Round1,Ready Go”的游戏回合页面,然后才是正式游戏概况页。
为此,咱们需求创建一个新的SwiftUI页面来承载它,在Xcode左侧视图工具栏中新建一个SwiftUI文件,命名为GameDetailView
,如下图所示:
在“游戏回合”视图中,咱们能够看到几个页面元素:游戏回合数(Round1)、游戏规则(5米)、游戏规则阐明(间隔篮筐)、游戏成果(投中:0)。
因为上述的参数会跟着游戏更新内容,因而需求声明其变量进行存储,如下代码所示:
@State var roundNum:Int = 1
@State var distanceNum:Int = 5
@State var gameGoal:Int = 0
上述代码中,咱们声明晰3个变量:roundNum
游戏回合数、distanceNum
篮筐间隔、gameGoal
单回合游戏得分。这儿因为在后续要运用到数值计算,因而声明的变量都是Int
类型。
紧接着,咱们来剖析构建页面,如下代码所示:
// 游戏回合
func preStartView() -> some View {
VStack {
Spacer()
VStack(alignment: .center, spacing: 40) {
Text("Round" + String(roundNum))
.font(.system(size: 48, design: .rounded))
.bold()
.foregroundColor(.white)
VStack(alignment: .center, spacing: 20) {
Text(String(distanceNum) + "米")
.font(.system(size: 24))
.foregroundColor(.white)
.bold()
Text("间隔篮筐")
.font(.system(size: 17))
.foregroundColor(.white)
}
}
Spacer()
Spacer()
Text("投中: " + String(gameGoal))
.font(.system(size: 17))
.foregroundColor(.white)
}
}
上述代码中,咱们创建了一个新的视图preStartView
。
剖析下页面元素,Text回合数文字为首要文字,运用48号圆形字体款式,并设置bold加粗,foregroundColor文字填充色彩为白色,其余文字根本修饰符类型。
这儿科普一个知识点。
因为声明的变量是Int类型,而Text文字需求键入String类型的文本,因而需求将Int类型转化为String类型。SwiftUI对于类型转化能够直接运用类型包裹进行转化,示例:String(roundNum)
,如此便能够直接将roundNum游戏回合数转化为String类型的参数。
别的,咱们能够运用“+”对字符串进行拼接,组成一个新的字符串,示例:
“I”+”Love”+”You” 成果为 “ILoveYou”
回归正题,文字部分也是运用VStack笔直布局视图进行包裹元素,这儿的编程思想是“由中间向两边散开”,即相间隔较近的元素能够先组合成一个容器,再和外边的容器进行组合,便于设置视图元素之间的距离。
完结好单个preStartView视图后,咱们在Body中展现它,如下代码所示:
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
preStartView()
}
游戏中视图
在游戏回合视图展现后,用户会进入到“游戏中”视图,正式开端参与游戏。如下图所示:
空气投篮游戏的游戏视图很简答,还原在现实生活中的篮筐,由一个计分板和投篮的篮筐组成,而计分板分为两块,分别为个位数计分板和十位数计分板。
咱们首要要导入“篮筐”的图片,相同是在黑色布景下,咱们需求一张SVG格式的矢量图,如下图所示:
回到GameDetailView游戏概况页,咱们来构建游戏中视图的款式,因为需求统计计分板的分数,因而需求声明好变量部分,如下代码所示:
@State var unitsDigit: Int = 0
@State var tensDigit: Int = 0
上述代码中,unitsDigit
为计分板个位数,tensDigit
为计分板十位数。然后,咱们再构建款式部分,如下代码所示:
// 游戏页面
func playGameView() -> some View {
VStack(alignment: .center, spacing: 40) {
HStack(alignment: .center, spacing: 20) {
Text(String(unitsDigit))
.font(.system(size: 120))
.bold()
.foregroundColor(.white)
.padding(40)
.background(Color.gray)
.cornerRadius(8)
Text(String(tensDigit))
.font(.system(size: 120))
.bold()
.foregroundColor(.white)
.padding(40)
.background(Color.gray)
.cornerRadius(8)
}
Image("ball")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: UIScreen.main.bounds.size.width / 2)
}
}
上述代码,在playGameView
视图中,咱们运用HStack横向布局容器包裹了计分板的款式内容。
关于Text文字布景部分,SwiftUI供给的办法是运用padding撑开间隔,再运用background布景色彩填充撑开的距离,最终再运用cornerRadius设置圆角。
如此,便完成了计分板的款式效果,图片部分这儿就不多说了。
相同,前期什么的Int类型的参数,在Text文字组件中运用需求转化成String字符串类型,方可运用。
此时咱们就完结了2个页面:preStartView
游戏回合视图、playGameView
游戏中视图。这儿做页面的切换,咱们也能够声明一个参数来进行状况的切换,如下代码所示:
@State var isReady:Bool = false
然后经过声明好的isReady
参数进行页面间的切换,如下代码所示:
if isReady {
playGameView()
} else {
preStartView()
}
进入&回来
经过两个章节的学习,咱们完结了两个首要的视图:ContentView
主页视图、GameDetailView
游戏概况视图,共4个页面,接下来,咱们要将这4个页面串起来。
回到ContentView主页视图,咱们盘一盘逻辑,在用户点击游戏项时,将会进入到GameDetailView游戏概况视图,游戏概况页首要会展现回合视图,然后再开端游戏。
了解了根本的交互逻辑后,咱们先完结页面之间的跳转,这儿能够运用根据NavigationView顶部导航栏的跳转方式,如下代码所示:
NavigationView {
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
if isAffirmInWatch {
gameListView()
} else {
prepareView()
.onTapGesture {
self.isAffirmInWatch = true
}
}
}
}
上述代码中,需求运用NavigationView
将整个视图包裹起来,然后再在gameListView游戏列表视图中增加跳转办法,如下代码所示:
NavigationLink(destination: GameDetailView()) {
gameRowView(gameName: "投篮", gameHelpText: "手举球开端游戏", gameImage: "basketball")
}
如此,当咱们点击“投篮”的游戏项时,就会跳转到GameDetailView游戏概况页。
咱们来到GameDetailView游戏概况页,因为当时GameDetailView游戏概况页的isReady参数变量为false,因而GameDetailView游戏概况页会展现preStartView游戏回合视图。
咱们希望的交互是preStartView游戏回合视图在显示2秒后自动到playGameView游戏中视图。
这儿在页面载入时增加多一个办法,如下代码所示:
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
if isReady {
playGameView()
} else {
preStartView()
}
}
.onAppear(){
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.isReady = true
}
}
上述代码中,咱们在GameDetailView游戏概况页onAppear
展现时增加了一个在主线程上的操作,即根据当时时刻2秒钟后,切换isReady状况。
如此,咱们便完成了在用户进入GameDetailView游戏概况页时,先展现preStartView游戏回合视图,再展现preStartView游戏中视图了。
进入操作有了,最终是回来操作。
原有的回来按钮太丑了,咱们能够自定义一个回来按钮,如下代码所示:
// 回来上一页
func backButton() -> some View {
Button(action: {
}) {
Image(systemName: "chevron.left.circle")
.font(.system(size: 17))
.foregroundColor(.white)
}
}
并将它加到GameDetailView游戏概况页视图中,如下代码所示:
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
if isReady {
playGameView()
} else {
preStartView()
}
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: backButton())
回来的操作交互也很简单,咱们能够调用SwiftUI的通用回来办法,如下代码所示:
@Environment(.presentationMode) var mode
最终在点击backButton
回来按钮的时分运用回来办法,如下代码所示:
self.mode.wrappedValue.dismiss()
本章预览
完结后,咱们回到ContentView预览下全体项目。
本章小结
恭喜你,完结了本章的所有内容!
在本章中,咱们构建了游戏概况页的视图,并完结了概况页的两种状况页面,预备开端游戏和游戏中的状况页面,还完成了从主页跳转到概况页、回来主页的全过程。
空气投篮项目iOS端全体的交互内容根本就到这儿了,接下来咱们将持续运用MVVM开发模式调整iOS端的内容,后面还会完结Watch端的页面及其交互。
最终如果条件成熟,咱们将调用Apple供给的各种传感器来完结真实的交互体验。
请坚持期待吧~
版权声明
本文为稀土技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!