發佈&選擇發佈,使用SwiftUI搭建一個新建發佈彈窗(上)

語言: CN / TW / HK

theme: smartblue

攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第23天,點擊查看活動詳情

項目背景

在之前的章節中,我們探討過如果掘金客户端要做發佈文章功能,那麼入口應該放在那個地方。

當我們確定了入口後,目前掘金Web端支持發佈文章沸點,移動端估計也會同步融合這兩塊功能作為一個入口。

我們再深化一下,當我們點擊“發佈”功能入口時,客户端該如何進行交互?那麼本章中,我們就來完成這個交互頁面。

項目搭建

首先,創建一個新的SwiftUI項目,命名為PublishingView

1.png

頂部導航

我們暫定“發佈”功能的入口在頂部導航右邊,也就是頁面右上角。我們基於當前掘金客户端的佈局,來構建下整個頂部導航,設計稿示例:

2.png

我們來分析下結構,頂部導航由一個“直播”按鈕入口,一個“搜索欄”,以及一個“發佈”功能按鈕組成。

對於“搜索欄”的構建,我們需要聲明一個變量來綁定和存儲輸入的內容;以及當我們點擊“發佈”按鈕時會打開一個彈窗頁面,我們也需要一個變量來存儲打開的狀態,示例:

@State var searchText = “" @State var showMaskView: Bool = false

然後我們來完成整個頂部導航的樣式,示例:

``` // 搜索欄 func topBarMenu() -> some View {     HStack(spacing: 15) {

// 直播         Button(action: {         }) {             Image(systemName: "video.square")                 .font(.system(size: 24))                 .foregroundColor(.gray)         }

TextField("搜索文如秋雨", text: $searchText)             .padding(7)             .padding(.horizontal, 25)             .background(Color(.systemGray6))             .cornerRadius(8)             .overlay(                 Image(systemName: "magnifyingglass")                     .foregroundColor(.gray)                     .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).padding(.leading, 8)             )

// 新建發佈         Button(action: {             withAnimation {                 self.showMaskView = true             }         }) {             Image(systemName: "plus.circle.fill")                 .font(.system(size: 24))                 .foregroundColor(.blue)         }     }.padding(.horizontal, 15) } ```

上述代碼中,我們構建了一個新的視圖topBarMenu

我們使用VStack縱向視圖排布了一個“直播”Button按鈕,一個搜索欄TextField輸入框,一個“發佈”Button按鈕。搜索欄TextField輸入框的內容綁定我們聲明好的變量searchText,“發佈”Button按鈕點擊時,切換showMaskView狀態打開彈窗。

然後我們在ContentView主視圖中構建樣式,示例:

var body: some View {     VStack {         topBarMenu()         Spacer()     } }

3.png

背景蒙層

當我們點擊“發佈“按鈕打開彈窗時,除了彈窗本身外,彈窗背後還有一個背景蒙層,我們可以單獨構建這個背景蒙層。示例:

``` // MARK: 蒙層 struct MaskView: View {     @Binding var showMaskView: Bool

var body: some View {         VStack {             Spacer()         }         .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)         .background(.black)         .edgesIgnoringSafeArea(.all)         .opacity(0.2)         .onTapGesture {             self.showMaskView = false         }     } } ```

上述代碼中,我們使用結構體的方式抽離出背景蒙層MaskView

MaskView結構體中,我們使用@Binding方便我們做雙向綁定,然後使用edgesIgnoringSafeArea修飾符構建一個滿屏的頁面,這個頁面背景顏色透明度為0.2的黑色,這樣我們就完成了背景蒙層的設計。

交互方面,當我們點擊背景蒙層時,切換showMaskView狀態,以實現關閉彈窗。

我們在ContentView主視圖使用MaskView背景蒙層看看效果,示例:

var body: some View {     ZStack {         VStack {             topBarMenu()             Spacer()         }         if showMaskView {             MaskView(showMaskView: $showMaskView)         }     } }

上述代碼中,我們通過判斷showMaskView狀態的值,來實現顯示MaskView背景蒙層,點擊運行預覽下項目:

4.gif

未完待續

由於彈窗的樣式和交互邏輯較為複雜,這裏將項目分為上下兩章來實現。上篇我們完成頂部導航和背景蒙層的設計,下篇我們來實現下彈窗的彈出、收起、拖動等功能交互。

快來動手試試吧。

如果本專欄對你有幫助,不妨點贊、評論、關注~

「其他文章」