簡體   English   中英

具有多個進度的 UIProgressView

[英]UIProgressView with multiple progress

如何在 ios 中構建具有多個進度的進度條? 我認為UIProgressView 不可能

我正在尋找這樣的東西(僅限用戶界面): 進度條 謝謝!

標准的UIProgressView僅顯示一個進度,如果您嘗試捕獲多個項目的進度,您將擁有Progress / NSProgress對象的層次結構。 例如,如果上傳五個文件,您有五個Progress對象,每個上傳一個,然后有第六個NSProgressUIProgressView觀察到,其他五個作為子級。 請參閱NSProgress 類參考中的創建進度對象樹 有關示例,請參見https://stackoverflow.com/a/36616538/1271826

如果您想要一個進度視圖來直觀地表示單個NSProgress的相應進度,則您必須自己執行此操作(或找到執行此操作的第三方控件)。 但是標准的UIProgressView不會為你做這件事。

但這並不難。 例如,您可以創建一個水平堆棧視圖,為每個要跟蹤的NSProgress添加一個UIProgressView ,將UIProgressView子視圖的相應寬度設置為例如它們代表整個任務的任何百分比。

例如,這是一個水平堆棧視圖,其中包含三個UIProgressView排列的子視圖:

在此處輸入圖片說明

話雖如此,我更喜歡標准的單一、統一的UIProgessView因為用戶可以更輕松地看到它們的距離。 如果你有一系列這樣的進度視圖,真的很難直觀地看到“我還有多長時間”,因為你必須查看所有單獨的進度視圖並在頭腦中弄清楚(例如“第一個看起來像是 50 % 完成,第二個完成 66%,第三個完成 75% ......那么整個事情到底有多遠?!?”)。

無論如何,這里是我的 Swift 代碼來呈現上述內容。 我知道您正在尋找 Objective-C,但希望這足以說明可以在 Swift 或 Objective-C 中輕松實現的基本思想:

class MultiProgressView: UIStackView {

    struct ProgressInfo {
        let progressView: UIProgressView
        let totalToken: NSKeyValueObservation
        let progressToken: NSKeyValueObservation
    }
    var progressInfo = [ProgressInfo]()
    var progressHandler: ((Double) -> Void)?

    var widthConstraints: [NSLayoutConstraint]?

    func add(_ progress: Progress, progressTintColor: UIColor = .blue, trackTintColor: UIColor? = nil) {
        let progressView = UIProgressView(progressViewStyle: .bar)
        progressView.translatesAutoresizingMaskIntoConstraints = false
        progressView.progressTintColor = progressTintColor
        progressView.trackTintColor = trackTintColor ?? progressTintColor.withAlphaComponent(0.5)
        addArrangedSubview(progressView)
        progressView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 1)
        progressView.observedProgress = progress
        let totalToken = progress.observe(\.totalUnitCount) { [weak self] (_, _) in
            self?.updateWidths()
        }
        let progressToken = progress.observe(\.completedUnitCount) { [weak self] (_, _) in
            if let percent = self?.percent {
                self?.progressHandler?(percent)
            }
        }
        progressInfo.append(ProgressInfo(progressView: progressView, totalToken: totalToken, progressToken: progressToken))
        updateWidths()
    }

    private func updateWidths() {
        if let widthConstraints = self.widthConstraints {
            removeConstraints(widthConstraints)
        }

        let totalUnitCount = self.totalUnitCount
        guard totalUnitCount > 0 else { return }

        widthConstraints = progressInfo.map { progressInfo in
            let unitCount = progressInfo.progressView.observedProgress?.totalUnitCount ?? 0
            return NSLayoutConstraint(item: progressInfo.progressView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: CGFloat(unitCount) / CGFloat(totalUnitCount), constant: 0)
        }

        DispatchQueue.main.async {
            self.addConstraints(self.widthConstraints!)
        }
    }

    var totalUnitCount: Int64 {
        return progressInfo.reduce(Int64(0)) { $0 + ($1.progressView.observedProgress?.totalUnitCount ?? 0) }
    }

    var completedUnitCount: Int64 {
        return progressInfo.reduce(Int64(0)) { $0 + ($1.progressView.observedProgress?.completedUnitCount ?? 0) }
    }

    var percent: Double {
        return Double(completedUnitCount) / Double(totalUnitCount)
    }
}

然后使用它:

override func viewDidLoad() {
    super.viewDidLoad()

    let download1 = Download(...)
    let download2 = Download(...)
    let download3 = Download(...)

    mainProgressView.progressHandler = { [weak self] percent in
        self?.checkIfDone(percent: percent)
    }

    mainProgressView.add(download1.progress, progressTintColor: .blue)
    mainProgressView.add(download2.progress, progressTintColor: .green)
    mainProgressView.add(download3.progress, progressTintColor: .red)

    download1.startDownload()
    download2.startDownload()
    download3.startDownload()
}

private func checkIfDone(percent: Double) {
    if percent == 1 {
        print("done")
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM