使用 SwiftUI 的 UI 元件 & data binding 創作有趣的 App -SAO註冊系統

老實說這次作業時間有點短再加上實在沒有想到什麼有趣點子,於是就搭配上一次的作業寫了SAO的註冊系統,讓那些公測沒有上線的玩家過過乾癮。

功能需求:

  • 畫面上至少需包含以下元件,而且程式也有使用這些元件。

Text,Image,Button,Date Picker,Form,Picker,Slider,TextField,TextEditor,Toggle,Stepper。

  • 使用到 SwiftUI 的 @State & @Binding。
  • 利用 DisclosureGroup 控制 Form 裡有些欄位顯示 / 隱藏。
  • 顯示 Alert。
  • 利用 function sheet & fullScreenCover 切換頁面。
  • 使用 ColorPicker 選顏色。

程式碼:

import SwiftUI
struct ContentView: View {
private let pictureVec = ["桐人頭","克萊茵頭","亞斯納頭","犀利卡頭","茅場頭","麗姿頭"]
private let pictureFullVec = ["桐人","克萊茵","亞斯納","犀利卡","茅場","麗姿"]
@State private var index = 0
@State private var color : Color = Color.white
@State private var level = 1
@State private var info : String = ""
@State private var name : String = ""
@State private var attack : Double = 50
@State private var defense : Double = 50
@State private var health : Double = 50
@State private var reaction : Double = 50
@State private var agile : Double = 50
@State private var skill : String = ""
@State private var showAlert : Bool = false
@State private var birth = Date()
@State private var customize = false
@State private var showSheet = false
var body: some View {
VStack {
Button(action: {
showSheet = true
}, label: {
Image("\(pictureVec[index])").resizable().scaledToFit().frame(height:200).background(color).sheet(isPresented: $showSheet){
CharacterView(name: pictureFullVec[index])
}
})
Form {
Section("基本資料設定"){
HStack{
Text("頭像選擇:")
Picker(selection: $index, label: Text(pictureVec[index])) {
Text("桐人").tag(0)
Text("克萊茵").tag(1)
Text("亞絲娜").tag(2)
Text("西莉卡").tag(3)
Text("希茲克利夫").tag(4)
Text("莉茲").tag(5)
}.pickerStyle(.menu)
}
HStack{
Text("角色名稱:")
TextField("請輸入角色名稱",text: $name)
}
HStack{
DatePicker("生日:",selection: $birth,displayedComponents: .date)
}
HStack{
ColorPicker("頭像背景顏色:", selection: $color)
}
}
Section("遊戲資料設定"){
HStack{
Text("初始等級設定:")
Stepper(value: $level, in: 1...10) {
Text("\(level)")
}
}
DisclosureGroup("角色數值"){
HStack{
Toggle("自訂數值", isOn: $customize)
}
HStack{
Text("攻擊:")
Slider(value: $attack,in:0...100).disabled(!customize)
Text("\(attack,specifier: "%.1f")")
}
HStack{
Text("血量:")
Slider(value: $health,in:0...100).disabled(!customize)
Text("\(health,specifier: "%.1f")")
}
HStack{
Text("防禦:")
Slider(value: $defense,in:0...100).disabled(!customize)
Text("\(defense,specifier: "%.1f")")
}
HStack{
Text("敏捷:")
Slider(value: $agile,in:0...100)
.disabled(!customize)
Text("\(agile,specifier: "%.1f")")
}
HStack{
Text("反應速度:")
Slider(value: $reaction,in:0...100).disabled(!customize)
Text("\(reaction,specifier: "%.1f")")
}
HStack(){
Button(action: {
attack = Double.random(in: 0...100)
defense = Double.random(in: 0...100)
health = Double.random(in: 0...100)
reaction = Double.random(in: 0...100)
agile = Double.random(in: 0...100)
}) {
HStack{
Image(systemName: "dice")
Text("隨機數值")
}
.padding(10)
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(50)
}
}.offset(x:75)
HStack{
Text("技能名稱:")
TextField("請輸入招式名稱",text: $skill)
}
HStack(alignment: .top){
Text("個人資訊:").padding(.top,8)
TextEditor(text: $info).frame(height: 100).border(.gray)
}
}
}

}
HStack{
Button(action: {
index = 0
color = Color.white
level = 1
info = ""
name = ""
attack = 50
defense = 50
health = 50
reaction = 50
agile = 50
skill = ""
birth = Date()
customize = false
}) {
HStack{
Image(systemName: "arrow.counterclockwise")
Text("重設")
}
.padding(10)
.foregroundColor(.white)
.background(Color.red)
.cornerRadius(50)
}

Button{
showAlert = true
}label:{
HStack{
Image(systemName: "rectangle.portrait.and.arrow.right.fill")
Text("儲存")
}
.padding(10)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(50)
}.alert("註冊成功", isPresented: $showAlert, actions:{Button("OK"){}} )
}
}
}
}
struct CharacterView: View {
let name : String
var body: some View {
Image(name).resizable().scaledToFit()
}
}

APP畫面截圖:

--

--