SwiftUI 框架

如何使用 ProgressView 和 ProgressViewStyle 自訂義進度條樣式

SwiftUI 框架提供了一個內置組件,稱為 ProgressView,供開發人員展示進度條或圓形指示器來顯示長時間運行操作的進度。本篇文章將詳細說明如何實作進度條和自訂義進度條樣式。
如何使用 ProgressView 和 ProgressViewStyle 自訂義進度條樣式
Photo by Mike van den Bos / Unsplash
In: SwiftUI 框架

在 App 設計中,進度條(Progress Bar)或其他類似的指示器在執行比較耗時的任務時,能發揮重要的作用。透過顯示進度讓使用者大概了解完成操作需要多長時間,令用戶體驗得以提升。

SwiftUI 框架提供了一個內置組件,稱為 ProgressView,供開發人員展示進度條或圓形指示器來顯示長時間運行操作的進度,例如下載文件或上傳數據到服務器。

ProgressView 的預設外觀簡單,可能不符合您的 App 設計和主題。這就是 ProgressViewStyle 協議發揮作用的地方。您可以使用 ProgressViewStyle 協議為 ProgressView 組件創建與您的App設計和主題相匹配的自定義樣式。

在本教學中,我將介紹 ProgressView 的基礎知識,並向您展示如何使用 ProgressViewStyle 自定義進度視圖的外觀。

ProgressView 基礎操作

ProgressView 組件非常容易使用。在您的 SwiftUI App 中,您可以通過編寫以下程式碼來建立進度指示器:

ProgressView()

您還可以選擇性地添加標籤以顯示狀態消息,例如:

ProgressView() {
    Text("加載中...")
}

在 iOS 上,進度視圖顯示為圓形指示器。

不確定進度(Indeterminate Progress)和確定進度(Determinate Progress)

ProgressView 組件提供了兩種類型的進度指示器,用於顯示不確定進度(Indeterminate Progress)和確定進度(Determinate Progress)。在前一節中展示的是不確定進度指示器。對於持續執行而未有確實完成時間的任務,例如加載或同步複雜數據,我們通常會使用不確定進度指示器(即是圓形活動指示器)。

在可能的情況下,請使用確定進度指示器。 不確定進度指示器顯示進程正在進行,但它無法幫助使用者估計任務需要多長時間。確定進度指示器可以幫助使用者決定在等待任務完成時是否要做其他事情,是否要在不同的時間重新啟動任務,或者是否要放棄任務。
- 蘋果的人機界面指南

對於具有明確時間長度的任務(例如文件下載),可以使用確定進度指示器。在 iOS 上,確定進度指示器是以進度條的形式呈現。要實現這一點,您只需要使用當前進度值建立 ProgressView。以下是一個示例:

ProgressView(value: 0.3)

在預設的情況下,總值為 1.0。您可以提供介於 0.0 和 1.0 之間的值,其中 1.0 即表示 100% 完成。如果您必須使用不同範圍和不同總值,則可以使用另一個初始化器編寫程式碼:

ProgressView(value: 30, total: 100)

這兩行程式碼都顯示了相同的進度指示器,表示已完成 30%。

您還可以選擇性添加一些標籤,以使用 labelcurrentValueLabel 參數顯示狀態消息和當前進度:

ProgressView(value: 0.3,
             label: { Text("Processing...") },
             currentValueLabel: { Text("30%") })

要更新進度的值,通常會創建一個狀態變數來保存進度的當前值。以下是一個示例程式碼:

struct ContentView: View {
    @State private var progressValue = 0.0
    
    var body: some View {
        VStack {
            ProgressView(value: progressValue, total: 1.0)
                .padding()
            Button("Start") {
                // Start the task
                // Update the progress value periodically
                for i in 1...5 {
                    progressValue = Double(i) / 5.0
                    Thread.sleep(forTimeInterval: 1.0)
                }
            }
        }
    }
}

更改進度視圖的顏色和樣式

預設的進度指示器具有簡單的設計和有限的自定義選項。但是,你可以通過應用 tint 修飾器來修改進度條的顏色:

ProgressView(value: 0.3)
    .tint(.purple)

確定進度指示器通常顯示為進度條。如果您希望修改其外觀,可以使用 progressViewStyle 修飾器。例如,您可以從預設的 linear 樣式切換至 circular 樣式,如下所示:

ProgressView(value: 0.3, label: { Text("Processing...") }, currentValueLabel: { Text("30%") })
    .progressViewStyle(.circular)

這就可以將進度條轉換為圓形指示器。

使用 ProgressViewStyle 作進階設定

雖然進度視圖的預設樣式對大多數 Apps 已經足夠,但您可能還是希望建立與 App 設計相匹配的進度條。如果您想創建更複雜的自定義進度條,就要學習使用 ProgressViewStyle 協議。

ProgressViewStyle 是 SwiftUI 中創建自定義進度指示器的強大工具。通過 ProgressViewStyle,您可以建立獨特且視覺上吸引人的進度條,完美地配合您的 App 設計和主題。SwiftUI 已有內置幾種樣式直接使用,例如 CircularProgressViewStyleLinearProgressViewStyle。通過符合 ProgressViewStyle 協議,您可以創建自己的樣式並將其應用於 ProgressView 組件。

為了讓您更好地了解 ProgressViewStyle,讓我們構建一個像上面所示的自定義進度條。您需要做的是創建一個新的結構(struct),符合 ProgressViewStyle 協議並實現以下所需方法:

@ViewBuilder func makeBody(configuration: Self.Configuration) -> Self.Body

如果您有使用 ButtonStyle 的經驗,ProgressViewStyle 的實作非常類似,因為它遵循相同的模式。

讓我們建立一個名為 BarProgressStyle 的新樣式,如下所示:

struct BarProgressStyle: ProgressViewStyle {
    
    var color: Color = .purple
    var height: Double = 20.0
    var labelFontStyle: Font = .body
    
    func makeBody(configuration: Configuration) -> some View {
        
        let progress = configuration.fractionCompleted ?? 0.0
        
        GeometryReader { geometry in
            
            VStack(alignment: .leading) {
                
                configuration.label
                    .font(labelFontStyle)
                
                RoundedRectangle(cornerRadius: 10.0)
                    .fill(Color(uiColor: .systemGray5))
                    .frame(height: height)
                    .frame(width: geometry.size.width)
                    .overlay(alignment: .leading) {
                        RoundedRectangle(cornerRadius: 10.0)
                            .fill(color)
                            .frame(width: geometry.size.width * progress)
                            .overlay {
                                if let currentValueLabel = configuration.currentValueLabel {
                                    
                                    currentValueLabel
                                        .font(.headline)
                                        .foregroundColor(.white)
                                }
                            }
                    }
                
            }
            
        }
    }
}

這個自定義樣式需要三個參數來配置進度條的顏色、高度和字體樣式。我不會一行一行地解釋 makeBody 方法中的程式碼。簡而言之,我們通過在灰色的另一個 RoundedRectangle 視圖的頂部覆蓋一個紫色的 RoundedRectangle 視圖來實現自己的進度條樣式。

configuration 參數為您提供進度視圖的常見屬性,包括:

  • fractionCompleted - 由進度視圖表示的任務完成的部分,從 0.0(尚未開始)到 1.0(完全完成)。
  • label - 狀態標籤。
  • currentValueLabel - 顯示當前進度的標籤。

現在,我們已經建立了自己的樣式,您可以通過將 progressViewStyle 修飾器附加到進度視圖來應用它:

ProgressView(value: 0.3, label: { Text("Processing...") }, currentValueLabel: { Text("30%") })
    .progressViewStyle(BarProgressStyle(height: 100.0))

作業

了解了 ProgressViewStyle 的基礎知識後,現在是時候將這些知識付諸實踐,創建一個新的自定義樣式了。您可以挑戰自己,試圖建立一個與下面圖片相似的樣式。這作業不僅可以幫助您鞏固所學的知識,還可以訓練實作不同外觀的進度視圖。

總結

從本教學中,我們介紹了如何使用 ProgressView 以顯示耗時任務或操作的進度。在合適的情況下,我們建議盡量使用確定進度指示器,因為它可以為使用者提供更準確的等候時間。

儘管預設進度視圖對大多數 Apps 都已足夠,使用 ProgressViewStyle 協議創建自定義進度視圖還是需要的。通過之前概述的步驟,您現在應該已經掌握了自定義進度視圖的基礎知識。

作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 16 App 程式設計實戰心法》、《iOS 16 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何在 SwiftUI 使用 Preview Macro
SwiftUI 框架

如何在 SwiftUI 使用 Preview Macro

SwiftUI 中的預覽(Preview)功能允許開發人員在不運行應用程序於設備或模擬器上的情況下,實時查看App的外觀。這個功能對於那些希望快速迭代設計並確保一切看起來和運作如預期的開發人員來說非常有用。隨著 iOS 17 中引入了巨集(Macro)的功能,預覽功能變得更加強大和靈活,提供了更多的自定義和靈活性。在本教學中,我們將探索如何在 SwiftUI 中使用新的預覽巨集(Preview Macro)
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。