SwiftUI教程(六)SwiftUI實(shí)戰(zhàn)之應(yīng)用商城

SwiftUI教程系列文章匯總

本文使用常見的View和Modifiers進(jìn)行布局,實(shí)現(xiàn)應(yīng)用商城的界面。通過具體的案例實(shí)現(xiàn),可以更好的熟悉SwiftUI的使用

效果:

效果示意

簡(jiǎn)單介紹:

實(shí)現(xiàn)應(yīng)用商城的游戲界面,分為三部分:標(biāo)題欄、推薦游戲、周邊游戲。
標(biāo)題欄會(huì)顯示標(biāo)題、頭像、更新數(shù)字
推薦游戲:標(biāo)題、描述、游戲圖片??梢宰笥一瑒?dòng)
周邊游戲:標(biāo)題、描述、多個(gè)游戲選項(xiàng)??梢陨舷禄瑒?dòng)

分析如何實(shí)現(xiàn):

整體布局:

  1. 界面可以實(shí)現(xiàn)導(dǎo)航效果,所以需要使用NavigationView
  2. 界面可以上下滑動(dòng),所以需要使用ScrollView
  3. 界面需要上下布局,所以使用VStack進(jìn)行布局
  4. 三部分使用Divider()實(shí)現(xiàn)分割效果

標(biāo)題欄:

  1. 頭像是給Divider視圖上方進(jìn)行覆蓋
  2. 更新數(shù)字覆蓋在頭像上方

推薦游戲:

  1. 左右滑動(dòng)通過TabView實(shí)現(xiàn)。
  2. 每一個(gè)界面使用VStack來實(shí)現(xiàn)每行顯示
  3. 游戲圖片中通過overlay覆蓋其他文字和圖片

周邊游戲:

  1. 標(biāo)題和描述不需要滑動(dòng),因此直接進(jìn)行設(shè)置
  2. 下方的多個(gè)游戲選項(xiàng)可以左右滑動(dòng),使用TabView
  3. 下方的多個(gè)游戲選項(xiàng)可以上下滑動(dòng),使用List實(shí)現(xiàn)

主要學(xué)習(xí):

  1. 布局
  2. NavigationView
  3. Divider
  4. TabView
  5. List
  6. overlay

實(shí)現(xiàn)過程:

整體布局

NavigationView {
    ScrollView {
        VStack {
        }
    }
}.navigationTitle("游戲")

說明:

  1. NavigationView用來實(shí)現(xiàn)界面導(dǎo)航效果。使用navigationTitle實(shí)現(xiàn)游戲標(biāo)題
  2. ScrollView可以讓界面view上下滑動(dòng),就和OC中的UIScrollView一樣
  3. 在界面中使用VStack實(shí)現(xiàn)垂直布局。

標(biāo)題欄

Divider().padding(EdgeInsets.init(top: 20, leading: 20, bottom: 0, trailing: 20))
.overlay {
    AsyncImage(url: URL.init(string: img2), content: { img in
        img.resizable()
    }, placeholder: {
        ProgressView()
    }).frame(width: 50, height: 50).cornerRadius(25)
        .overlay {
            Text("83").frame(width: 32, height: 20).background(.red).cornerRadius(10).foregroundColor(.white).padding(EdgeInsets.init(top: -30, leading: 30, bottom: 0, trailing: 0))
        }.padding(EdgeInsets.init(top: -64, leading: 300, bottom: 0, trailing: 0))
}

說明:

  1. Divider()是一個(gè)分割線視圖
  2. 使用padding來填充空白到視圖的周圍,使用你指定的邊和填充量來進(jìn)行設(shè)置,這里使用了EdgeInsets來設(shè)置上下左右的填充量。
  3. 在一個(gè)視圖上面想要覆蓋一個(gè)視圖,就需要使用overlay來實(shí)現(xiàn)。這里給Divider來覆蓋一個(gè)頭像視圖
  4. AsyncImage用來異步加載圖片,因?yàn)橛锌赡軟]有加載成功,所以使用placeholder設(shè)置加載失敗后的占位(可以設(shè)置圖片、可以設(shè)置文字、也可以像這里設(shè)置加載視圖)
  5. 給頭像覆蓋一個(gè)視圖,設(shè)置一個(gè)文字,使用Text("83")進(jìn)行設(shè)置
  6. Text的設(shè)置很簡(jiǎn)單,就不詳細(xì)說明了。

推薦游戲

 TabView {
    ForEach($items, id: \.self) {_ in
        VStack {
            HStack {
                Text("重磅更新").foregroundColor(.blue).fontWeight(.bold)
                Spacer()
            }
            HStack {
                Text("地下城堡3:魂之詩(shī)").font(.title)
                Spacer()
            }
            HStack {
                Text("新地圖“廢械陣”上線").font(.title2).foregroundColor(.gray)
                Spacer()
            }
            AsyncImage(url: URL.init(string: img1)) { img in
                img.resizable()
            } placeholder: {
                ProgressView()
            }
            .frame(height: 220)
            .cornerRadius(10)
            .overlay {
                VStack {
                    Spacer()
                    HStack {
                        AsyncImage(url: URL.init(string: img2)) { img in
                            img.resizable()
                        } placeholder: {
                            ProgressView()
                        }
                        .frame(width: 50, height: 50).cornerRadius(12)
                        VStack {
                            HStack {
                                Text("地下城堡3:魂之詩(shī)").foregroundColor(.white).font(.title3)
                                Spacer()
                            }
                            HStack {
                                Text("暗黑文字地牢探險(xiǎn)").foregroundColor(.gray)
                                Spacer()
                            }
                        }
                        Spacer()
                        VStack {
                            Button("獲取") {
                                print("get")
                            }.foregroundColor(.white).font(Font.system(.title2).bold()).frame(width: 94, height: 40).background(.gray.opacity(0.8)).cornerRadius(20)
                            Text("App內(nèi)購(gòu)買").foregroundColor(.gray).font(.footnote)
                        }.padding(.top, 15)
                    }
                    .padding(EdgeInsets.init(top: 0, leading: 16, bottom: 6, trailing: 16))
                    .background(LinearGradient(colors: [.black.opacity(0.5), .clear], startPoint: .bottom, endPoint: .top)).cornerRadius(12)
                }
            }
        }.padding(20)
    }
}
.frame(width: ScreenWidth, height: 320)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))

說明:

  1. TabView可以看做OC中的tabbar,可以實(shí)現(xiàn)左右滑動(dòng)(不要誤以為是UITableView)
  2. ForEach設(shè)置多行,以此實(shí)現(xiàn)左右滑動(dòng)
  3. 為了縱向可以給Text設(shè)置特定位置,使用HStack
  4. Spacer()用來設(shè)置空視圖
  5. cornerRadius用來設(shè)置邊框圓角角度
  6. 在這里為了方便調(diào)整視圖位置,都使用到了Spacer()。并且因?yàn)樗旧硪彩且粋€(gè)視圖,所以需要放到Stack中
  7. 此處按鈕的響應(yīng)事件只進(jìn)行了打印。在實(shí)際開發(fā)中這里應(yīng)該是要跳轉(zhuǎn)界面
  8. .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))設(shè)置TabView的類型,這里是設(shè)置了分頁(yè)查看,設(shè)置成這種類型就可以左右滑動(dòng)查看。而且還設(shè)置了不顯示小點(diǎn)點(diǎn)

周邊游戲:

代碼:

 VStack {
    HStack {
        Text("我們都在玩").font(.title).bold()
        Spacer()
        Button("查看全部") {
            print("all")
        }.font(.title2)
    }
    HStack {
        Text("探索本周游戲熱點(diǎn)").foregroundColor(.gray).font(.title2)
        Spacer()
    }
}.padding(EdgeInsets.init(top: 0, leading: 20, bottom: 0, trailing: 20))
    
TabView {
    ForEach($items, id: \.self) {_ in
        List(0..<3) {_ in
            HStack {
                AsyncImage(url: URL.init(string: img1)) { img in
                    img.resizable()
                } placeholder: {
                    ProgressView()
                }
                .frame(width: 68, height: 68).cornerRadius(16)
                VStack {
                    HStack {
                        Text("地下城堡3:魂之詩(shī)").font(.title3)
                        Spacer()
                    }
                    HStack {
                        Text("暗黑文字地牢探險(xiǎn)").foregroundColor(.gray)
                        Spacer()
                    }
                }
                Spacer()
                VStack {
                    Button("獲取") {
                        print("get")
                    }.foregroundColor(.blue).font(Font.system(.title2).bold()).frame(width: 94, height: 40).background(.gray.opacity(0.2)).cornerRadius(20)
                    Text("App內(nèi)購(gòu)買").foregroundColor(.gray).font(.footnote)
                }
            }
        }.listStyle(InsetListStyle())//.listRowSeparator(.hidden)
    }
}
.frame(width: ScreenWidth, height: 270)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))

說明:

  1. 這里其實(shí)分成了兩部分,第一部分是標(biāo)題描述,第二部分是游戲顯示
  2. 第一部分很簡(jiǎn)單,只使用到了Stack、Text、Button。上面已經(jīng)講過這些視圖的使用了
  3. 依然使用TabView實(shí)現(xiàn)左右滑動(dòng)
  4. List可以實(shí)現(xiàn)列表顯示,.listStyle(InsetListStyle())設(shè)置list的類型
  5. 每個(gè)列表都顯示各自的游戲圖片和說明
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容